From 66f33ad49771aebdb2d41341728fa36ba59f3fd3 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Wed, 15 Apr 2020 13:36:25 -0700 Subject: [PATCH] Use manfiests to render doc urls (#5549) * Use manfiests to render doc urls * Update UI --- src/data/integration.ts | 26 ++++- src/data/system_log.ts | 2 + .../developer-tools/info/integrations-card.ts | 103 ++++++++++++------ .../logs/dialog-system-log-detail.ts | 62 ++++++++--- 4 files changed, 143 insertions(+), 50 deletions(-) diff --git a/src/data/integration.ts b/src/data/integration.ts index f322e96f10..7607bd3dcb 100644 --- a/src/data/integration.ts +++ b/src/data/integration.ts @@ -1,10 +1,32 @@ import { LocalizeFunc } from "../common/translations/localize"; +import { HomeAssistant } from "../types"; -export const integrationDocsUrl = (domain: string) => - `https://www.home-assistant.io/integrations/${domain}`; +export interface IntegrationManifest { + is_built_in: boolean; + domain: string; + name: string; + config_flow: boolean; + documentation: string; + dependencies?: string[]; + after_dependencies?: string[]; + codeowners?: string[]; + requirements?: string[]; + ssdp?: Array<{ manufacturer?: string; modelName?: string; st?: string }>; + zeroconf?: string[]; + homekit?: { models: string[] }; + quality_scale?: string; +} export const integrationIssuesUrl = (domain: string) => `https://github.com/home-assistant/home-assistant/issues?q=is%3Aissue+is%3Aopen+label%3A%22integration%3A+${domain}%22`; export const domainToName = (localize: LocalizeFunc, domain: string) => localize(`domain.${domain}`) || domain; + +export const fetchIntegrationManifests = (hass: HomeAssistant) => + hass.callWS({ type: "manifest/list" }); + +export const fetchIntegrationManifest = ( + hass: HomeAssistant, + integration: string +) => hass.callWS({ type: "manifest/get", integration }); diff --git a/src/data/system_log.ts b/src/data/system_log.ts index 9257c31080..865558ebb9 100644 --- a/src/data/system_log.ts +++ b/src/data/system_log.ts @@ -19,4 +19,6 @@ export const fetchSystemLog = (hass: HomeAssistant) => export const getLoggedErrorIntegration = (item: LoggedError) => item.name.startsWith("homeassistant.components.") ? item.name.split(".")[2] + : item.name.startsWith("custom_components.") + ? item.name.split(".")[1] : undefined; diff --git a/src/panels/developer-tools/info/integrations-card.ts b/src/panels/developer-tools/info/integrations-card.ts index f01d5d5d89..12b6e29f59 100644 --- a/src/panels/developer-tools/info/integrations-card.ts +++ b/src/panels/developer-tools/info/integrations-card.ts @@ -9,8 +9,9 @@ import { } from "lit-element"; import memoizeOne from "memoize-one"; import { - integrationDocsUrl, integrationIssuesUrl, + IntegrationManifest, + fetchIntegrationManifests, } from "../../../data/integration"; import { HomeAssistant } from "../../../types"; @@ -18,46 +19,67 @@ import { HomeAssistant } from "../../../types"; class IntegrationsCard extends LitElement { @property() public hass!: HomeAssistant; + @property() private _manifests?: { [domain: string]: IntegrationManifest }; + private _sortedIntegrations = memoizeOne((components: string[]) => { return components.filter((comp) => !comp.includes(".")).sort(); }); + firstUpdated(changedProps) { + super.firstUpdated(changedProps); + this._fetchManifests(); + } + protected render(): TemplateResult { return html` ${this._sortedIntegrations(this.hass!.config.components).map( - (domain) => html` - - - - - - - ` + (domain) => { + const manifest = this._manifests && this._manifests[domain]; + return html` + + + + ${!manifest + ? "" + : html` + + ${!manifest.is_built_in + ? "" + : html` + + `} + `} + + `; + } )}
- - ${domain} - - Documentation - - - - Issues - -
+ + + ${manifest?.name}
+ ${domain} +
+ + Documentation + + + + Issues + +
@@ -65,19 +87,32 @@ class IntegrationsCard extends LitElement { `; } + private async _fetchManifests() { + const manifests = {}; + for (const manifest of await fetchIntegrationManifests(this.hass)) { + manifests[manifest.domain] = manifest; + } + this._manifests = manifests; + } + static get styles(): CSSResult { return css` td { - line-height: 2em; padding: 0 8px; } td:first-child { padding-left: 0; } + td.name { + padding: 8px; + } + .domain { + color: var(--secondary-text-color); + } img { display: block; - max-height: 24px; - max-width: 24px; + max-height: 40px; + max-width: 40px; } a { color: var(--primary-color); diff --git a/src/panels/developer-tools/logs/dialog-system-log-detail.ts b/src/panels/developer-tools/logs/dialog-system-log-detail.ts index c9b54b6943..255884558a 100644 --- a/src/panels/developer-tools/logs/dialog-system-log-detail.ts +++ b/src/panels/developer-tools/logs/dialog-system-log-detail.ts @@ -10,8 +10,9 @@ import { import "../../../components/dialog/ha-paper-dialog"; import { domainToName, - integrationDocsUrl, integrationIssuesUrl, + IntegrationManifest, + fetchIntegrationManifest, } from "../../../data/integration"; import { getLoggedErrorIntegration } from "../../../data/system_log"; import { PolymerChangedEvent } from "../../../polymer-types"; @@ -25,11 +26,25 @@ class DialogSystemLogDetail extends LitElement { @property() private _params?: SystemLogDetailDialogParams; + @property() private _manifest?: IntegrationManifest; + public async showDialog(params: SystemLogDetailDialogParams): Promise { this._params = params; + this._manifest = undefined; await this.updateComplete; } + protected updated(changedProps) { + super.updated(changedProps); + if (!changedProps.has("_params") || !this._params) { + return; + } + const integration = getLoggedErrorIntegration(this._params.item); + if (integration) { + this._fetchManifest(integration); + } + } + protected render(): TemplateResult { if (!this._params) { return html``; @@ -58,19 +73,30 @@ class DialogSystemLogDetail extends LitElement { ${integration ? html`
- Integration: ${domainToName(this.hass.localize, integration)} - (documentation, - issues) + Integration: + ${this._manifest + ? this._manifest.name + : domainToName(this.hass.localize, integration)} + ${!this._manifest || + // Can happen with custom integrations + !this._manifest.documentation + ? "" + : html` + (documentation${!this._manifest.is_built_in + ? "" + : html`, + issues`}) + `} ` : ""}
@@ -100,6 +126,14 @@ class DialogSystemLogDetail extends LitElement { `; } + private async _fetchManifest(integration: string) { + try { + this._manifest = await fetchIntegrationManifest(this.hass, integration); + } catch (err) { + // Ignore if loading manifest fails. Probably bad JSON in manifest + } + } + private _openedChanged(ev: PolymerChangedEvent): void { if (!(ev.detail as any).value) { this._params = undefined;