Move integrations to System Health (#12504)

This commit is contained in:
Zack Barett 2022-04-29 13:53:24 -05:00 committed by GitHub
parent 011467ece0
commit 591b8cc503
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 104 additions and 158 deletions

View File

@ -3,12 +3,12 @@ import { property, state } from "lit/decorators";
import { isComponentLoaded } from "../../../common/config/is_component_loaded"; import { isComponentLoaded } from "../../../common/config/is_component_loaded";
import "../../../components/ha-logo-svg"; import "../../../components/ha-logo-svg";
import { import {
fetchHassioHostInfo,
fetchHassioHassOsInfo, fetchHassioHassOsInfo,
fetchHassioHostInfo,
HassioHassOSInfo, HassioHassOSInfo,
HassioHostInfo, HassioHostInfo,
} from "../../../data/hassio/host"; } from "../../../data/hassio/host";
import { HassioInfo, fetchHassioInfo } from "../../../data/hassio/supervisor"; import { fetchHassioInfo, HassioInfo } from "../../../data/hassio/supervisor";
import "../../../layouts/hass-subpage"; import "../../../layouts/hass-subpage";
import { haStyle } from "../../../resources/styles"; import { haStyle } from "../../../resources/styles";
import { HomeAssistant, Route } from "../../../types"; import { HomeAssistant, Route } from "../../../types";
@ -153,12 +153,6 @@ class HaConfigInfo extends LitElement {
: ""} : ""}
</p> </p>
</div> </div>
<div>
<integrations-card
.hass=${this.hass}
.narrow=${this.narrow}
></integrations-card>
</div>
</hass-subpage> </hass-subpage>
`; `;
} }

View File

@ -1,16 +1,23 @@
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import "@material/mwc-list/mwc-list";
import {
css,
CSSResultGroup,
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 "../../../components/ha-clickable-list-item";
import { import {
domainToName, domainToName,
fetchIntegrationManifests, fetchIntegrationManifests,
fetchIntegrationSetups, fetchIntegrationSetups,
integrationIssuesUrl,
IntegrationManifest, IntegrationManifest,
IntegrationSetup, IntegrationSetup,
} from "../../../data/integration"; } from "../../../data/integration";
import { HomeAssistant } from "../../../types"; import type { 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";
@ -24,120 +31,69 @@ class IntegrationsCard extends LitElement {
[domain: string]: IntegrationManifest; [domain: string]: IntegrationManifest;
}; };
@state() private _setups?: { @state() private _setups?: IntegrationSetup[];
[domain: string]: IntegrationSetup;
};
private _sortedIntegrations = memoizeOne((components: string[]) => protected firstUpdated(changedProps: PropertyValues) {
Array.from(
new Set(
components.map((comp) =>
comp.includes(".") ? comp.split(".")[1] : comp
)
)
).sort()
);
firstUpdated(changedProps) {
super.firstUpdated(changedProps); super.firstUpdated(changedProps);
this._fetchManifests(); this._fetchManifests();
this._fetchSetups(); this._fetchSetups();
} }
protected render(): TemplateResult { protected render(): TemplateResult {
if (!this._setups) {
return html``;
}
return html` return html`
<ha-card <ha-card
.header=${this.hass.localize("ui.panel.config.info.integrations")} outlined
.header=${this.hass.localize(
"ui.panel.config.system_health.long_loading_integrations"
)}
> >
<table class="card-content"> <mwc-list>
<thead> ${this._setups?.map((setup) => {
<tr> const manifest = this._manifests && this._manifests[setup.domain];
<th></th>
${!this.narrow
? html`<th></th>
<th></th>
<th></th>`
: ""}
<th>${this.hass.localize("ui.panel.config.info.setup_time")}</th>
</tr>
</thead>
<tbody>
${this._sortedIntegrations(this.hass!.config.components).map(
(domain) => {
const manifest = this._manifests && this._manifests[domain];
const docLink = manifest const docLink = manifest
? html`<a ? manifest.is_built_in
href=${manifest.is_built_in
? documentationUrl( ? documentationUrl(
this.hass, this.hass,
`/integrations/${manifest.domain}` `/integrations/${manifest.domain}`
) )
: manifest.documentation} : manifest.documentation
target="_blank"
rel="noreferrer"
>${this.hass.localize(
"ui.panel.config.info.documentation"
)}</a
>`
: ""; : "";
const issueLink =
manifest && (manifest.is_built_in || manifest.issue_tracker) const setupSeconds = setup.seconds?.toFixed(2);
? html`
<a
href=${integrationIssuesUrl(domain, manifest)}
target="_blank"
rel="noreferrer"
>${this.hass.localize(
"ui.panel.config.info.issues"
)}</a
>
`
: "";
const setupSeconds =
this._setups?.[domain]?.seconds?.toFixed(2);
return html` return html`
<tr> <ha-clickable-list-item
<td> graphic="avatar"
twoline
hasMeta
@click=${this._entryClicked}
href=${docLink}
>
<img <img
loading="lazy" loading="lazy"
src=${brandsUrl({ src=${brandsUrl({
domain: domain, domain: setup.domain,
type: "icon", type: "icon",
useFallback: true, useFallback: true,
darkOptimized: this.hass.themes?.darkMode, darkOptimized: this.hass.themes?.darkMode,
})} })}
referrerpolicy="no-referrer" referrerpolicy="no-referrer"
slot="graphic"
/> />
</td> <span>
<td class="name"> ${domainToName(this.hass.localize, setup.domain, manifest)}
${domainToName( </span>
this.hass.localize, <span slot="secondary">${setup.domain}</span>
domain, <div slot="meta">
manifest
)}<br />
<span class="domain">${domain}</span>
${this.narrow
? html`<div class="mobile-row">
<div>${docLink} ${issueLink}</div>
${setupSeconds ? html`${setupSeconds} s` : ""} ${setupSeconds ? html`${setupSeconds} s` : ""}
</div>` </div>
: ""} </ha-clickable-list-item>
</td>
${this.narrow
? ""
: html`
<td>${docLink}</td>
<td>${issueLink}</td>
<td class="setup">
${setupSeconds ? html`${setupSeconds} s` : ""}
</td>
`}
</tr>
`; `;
} })}
)} </mwc-list>
</tbody>
</table>
</ha-card> </ha-card>
`; `;
} }
@ -151,54 +107,36 @@ class IntegrationsCard extends LitElement {
} }
private async _fetchSetups() { private async _fetchSetups() {
const setups = {}; const setups = await fetchIntegrationSetups(this.hass);
for (const setup of await fetchIntegrationSetups(this.hass)) { this._setups = setups.sort((a, b) => {
setups[setup.domain] = setup; if (a.seconds === b.seconds) {
return 0;
} }
this._setups = setups; if (a.seconds === undefined) {
return 1;
}
if (b.seconds === undefined) {
return 1;
}
return b.seconds - a.seconds;
});
}
private _entryClicked(ev) {
ev.currentTarget.blur();
} }
static get styles(): CSSResultGroup { static get styles(): CSSResultGroup {
return css` return css`
table { ha-clickable-list-item {
width: 100%; --mdc-list-item-meta-size: 48px;
} --mdc-typography-caption-font-size: 12px;
td,
th {
padding: 0 8px;
}
td:first-child {
padding-left: 0;
}
td.name {
padding: 8px;
}
td.setup {
text-align: right;
white-space: nowrap;
direction: ltr;
}
th {
text-align: right;
}
.domain {
color: var(--secondary-text-color);
}
.mobile-row {
display: flex;
justify-content: space-between;
}
.mobile-row a:not(:last-of-type) {
margin-right: 4px;
} }
img { img {
display: block; display: block;
max-height: 40px; max-height: 40px;
max-width: 40px; max-width: 40px;
} }
a {
color: var(--primary-color);
}
`; `;
} }
} }

View File

@ -30,6 +30,7 @@ import { SubscribeMixin } from "../../../mixins/subscribe-mixin";
import type { HomeAssistant } from "../../../types"; import type { HomeAssistant } from "../../../types";
import { documentationUrl } from "../../../util/documentation-url"; import { documentationUrl } from "../../../util/documentation-url";
import { showToast } from "../../../util/toast"; import { showToast } from "../../../util/toast";
import "../info/integrations-card";
const sortKeys = (a: string, b: string) => { const sortKeys = (a: string, b: string) => {
if (a === "homeassistant") { if (a === "homeassistant") {
@ -317,6 +318,11 @@ class HaConfigSystemHealth extends SubscribeMixin(LitElement) {
</div> </div>
</ha-card> </ha-card>
`} `}
<integrations-card
.hass=${this.hass}
.narrow=${this.narrow}
></integrations-card>
</div> </div>
</hass-subpage> </hass-subpage>
`; `;
@ -450,12 +456,20 @@ class HaConfigSystemHealth extends SubscribeMixin(LitElement) {
max-width: 1040px; max-width: 1040px;
margin: 0 auto; margin: 0 auto;
} }
integrations-card {
max-width: 600px;
display: block;
max-width: 600px;
margin: 0 auto;
margin-bottom: 24px;
margin-bottom: max(24px, env(safe-area-inset-bottom));
}
ha-card { ha-card {
display: block; display: block;
max-width: 600px; max-width: 600px;
margin: 0 auto; margin: 0 auto;
padding-bottom: 16px; padding-bottom: 16px;
margin-bottom: max(24px, env(safe-area-inset-bottom)); margin-bottom: 24px;
} }
ha-alert { ha-alert {
display: block; display: block;

View File

@ -1551,7 +1551,6 @@
"frontend_version": "Frontend version: {version} - {type}", "frontend_version": "Frontend version: {version} - {type}",
"custom_uis": "Custom UIs:", "custom_uis": "Custom UIs:",
"system_health_error": "System Health component is not loaded. Add 'system_health:' to configuration.yaml", "system_health_error": "System Health component is not loaded. Add 'system_health:' to configuration.yaml",
"integrations": "Integrations",
"documentation": "Documentation", "documentation": "Documentation",
"issues": "Issues", "issues": "Issues",
"setup_time": "Setup time", "setup_time": "Setup time",
@ -3164,10 +3163,11 @@
}, },
"system_health": { "system_health": {
"caption": "System Health", "caption": "System Health",
"cpu_usage": "Process Usage", "cpu_usage": "Processor Usage",
"ram_usage": "Memory Usage", "ram_usage": "Memory Usage",
"core_stats": "Core Stats", "core_stats": "Core Stats",
"supervisor_stats": "Supervisor Stats" "supervisor_stats": "Supervisor Stats",
"long_loading_integrations": "Long Loading Integrations"
}, },
"system_dashboard": { "system_dashboard": {
"confirm_restart_text": "Restarting Home Assistant will stop all your active dashboards, automations and scripts.", "confirm_restart_text": "Restarting Home Assistant will stop all your active dashboards, automations and scripts.",