mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-23 09:16:38 +00:00
Use manfiests to render doc urls (#5549)
* Use manfiests to render doc urls * Update UI
This commit is contained in:
parent
ff81536463
commit
66f33ad497
@ -1,10 +1,32 @@
|
|||||||
import { LocalizeFunc } from "../common/translations/localize";
|
import { LocalizeFunc } from "../common/translations/localize";
|
||||||
|
import { HomeAssistant } from "../types";
|
||||||
|
|
||||||
export const integrationDocsUrl = (domain: string) =>
|
export interface IntegrationManifest {
|
||||||
`https://www.home-assistant.io/integrations/${domain}`;
|
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) =>
|
export const integrationIssuesUrl = (domain: string) =>
|
||||||
`https://github.com/home-assistant/home-assistant/issues?q=is%3Aissue+is%3Aopen+label%3A%22integration%3A+${domain}%22`;
|
`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) =>
|
export const domainToName = (localize: LocalizeFunc, domain: string) =>
|
||||||
localize(`domain.${domain}`) || domain;
|
localize(`domain.${domain}`) || domain;
|
||||||
|
|
||||||
|
export const fetchIntegrationManifests = (hass: HomeAssistant) =>
|
||||||
|
hass.callWS<IntegrationManifest[]>({ type: "manifest/list" });
|
||||||
|
|
||||||
|
export const fetchIntegrationManifest = (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
integration: string
|
||||||
|
) => hass.callWS<IntegrationManifest>({ type: "manifest/get", integration });
|
||||||
|
@ -19,4 +19,6 @@ export const fetchSystemLog = (hass: HomeAssistant) =>
|
|||||||
export const getLoggedErrorIntegration = (item: LoggedError) =>
|
export const getLoggedErrorIntegration = (item: LoggedError) =>
|
||||||
item.name.startsWith("homeassistant.components.")
|
item.name.startsWith("homeassistant.components.")
|
||||||
? item.name.split(".")[2]
|
? item.name.split(".")[2]
|
||||||
|
: item.name.startsWith("custom_components.")
|
||||||
|
? item.name.split(".")[1]
|
||||||
: undefined;
|
: undefined;
|
||||||
|
@ -9,8 +9,9 @@ import {
|
|||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import {
|
import {
|
||||||
integrationDocsUrl,
|
|
||||||
integrationIssuesUrl,
|
integrationIssuesUrl,
|
||||||
|
IntegrationManifest,
|
||||||
|
fetchIntegrationManifests,
|
||||||
} from "../../../data/integration";
|
} from "../../../data/integration";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
|
|
||||||
@ -18,46 +19,67 @@ import { HomeAssistant } from "../../../types";
|
|||||||
class IntegrationsCard extends LitElement {
|
class IntegrationsCard extends LitElement {
|
||||||
@property() public hass!: HomeAssistant;
|
@property() public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@property() private _manifests?: { [domain: string]: IntegrationManifest };
|
||||||
|
|
||||||
private _sortedIntegrations = memoizeOne((components: string[]) => {
|
private _sortedIntegrations = memoizeOne((components: string[]) => {
|
||||||
return components.filter((comp) => !comp.includes(".")).sort();
|
return components.filter((comp) => !comp.includes(".")).sort();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
firstUpdated(changedProps) {
|
||||||
|
super.firstUpdated(changedProps);
|
||||||
|
this._fetchManifests();
|
||||||
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
<ha-card header="Integrations">
|
<ha-card header="Integrations">
|
||||||
<table class="card-content">
|
<table class="card-content">
|
||||||
<tbody>
|
<tbody>
|
||||||
${this._sortedIntegrations(this.hass!.config.components).map(
|
${this._sortedIntegrations(this.hass!.config.components).map(
|
||||||
(domain) => html`
|
(domain) => {
|
||||||
<tr>
|
const manifest = this._manifests && this._manifests[domain];
|
||||||
<td>
|
return html`
|
||||||
<img
|
<tr>
|
||||||
loading="lazy"
|
<td>
|
||||||
src="https://brands.home-assistant.io/_/${domain}/icon.png"
|
<img
|
||||||
referrerpolicy="no-referrer"
|
loading="lazy"
|
||||||
/>
|
src="https://brands.home-assistant.io/_/${domain}/icon.png"
|
||||||
</td>
|
referrerpolicy="no-referrer"
|
||||||
<td>${domain}</td>
|
/>
|
||||||
<td>
|
</td>
|
||||||
<a
|
<td class="name">
|
||||||
href=${integrationDocsUrl(domain)}
|
${manifest?.name}<br />
|
||||||
target="_blank"
|
<span class="domain">${domain}</span>
|
||||||
rel="noreferrer"
|
</td>
|
||||||
>
|
${!manifest
|
||||||
Documentation
|
? ""
|
||||||
</a>
|
: html`
|
||||||
</td>
|
<td>
|
||||||
<td>
|
<a
|
||||||
<a
|
href=${manifest.documentation}
|
||||||
href=${integrationIssuesUrl(domain)}
|
target="_blank"
|
||||||
target="_blank"
|
rel="noreferrer"
|
||||||
rel="noreferrer"
|
>
|
||||||
>
|
Documentation
|
||||||
Issues
|
</a>
|
||||||
</a>
|
</td>
|
||||||
</td>
|
${!manifest.is_built_in
|
||||||
</tr>
|
? ""
|
||||||
`
|
: html`
|
||||||
|
<td>
|
||||||
|
<a
|
||||||
|
href=${integrationIssuesUrl(domain)}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
Issues
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
`}
|
||||||
|
`}
|
||||||
|
</tr>
|
||||||
|
`;
|
||||||
|
}
|
||||||
)}
|
)}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@ -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 {
|
static get styles(): CSSResult {
|
||||||
return css`
|
return css`
|
||||||
td {
|
td {
|
||||||
line-height: 2em;
|
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
}
|
}
|
||||||
td:first-child {
|
td:first-child {
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
}
|
}
|
||||||
|
td.name {
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
.domain {
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
}
|
||||||
img {
|
img {
|
||||||
display: block;
|
display: block;
|
||||||
max-height: 24px;
|
max-height: 40px;
|
||||||
max-width: 24px;
|
max-width: 40px;
|
||||||
}
|
}
|
||||||
a {
|
a {
|
||||||
color: var(--primary-color);
|
color: var(--primary-color);
|
||||||
|
@ -10,8 +10,9 @@ import {
|
|||||||
import "../../../components/dialog/ha-paper-dialog";
|
import "../../../components/dialog/ha-paper-dialog";
|
||||||
import {
|
import {
|
||||||
domainToName,
|
domainToName,
|
||||||
integrationDocsUrl,
|
|
||||||
integrationIssuesUrl,
|
integrationIssuesUrl,
|
||||||
|
IntegrationManifest,
|
||||||
|
fetchIntegrationManifest,
|
||||||
} from "../../../data/integration";
|
} from "../../../data/integration";
|
||||||
import { getLoggedErrorIntegration } from "../../../data/system_log";
|
import { getLoggedErrorIntegration } from "../../../data/system_log";
|
||||||
import { PolymerChangedEvent } from "../../../polymer-types";
|
import { PolymerChangedEvent } from "../../../polymer-types";
|
||||||
@ -25,11 +26,25 @@ class DialogSystemLogDetail extends LitElement {
|
|||||||
|
|
||||||
@property() private _params?: SystemLogDetailDialogParams;
|
@property() private _params?: SystemLogDetailDialogParams;
|
||||||
|
|
||||||
|
@property() private _manifest?: IntegrationManifest;
|
||||||
|
|
||||||
public async showDialog(params: SystemLogDetailDialogParams): Promise<void> {
|
public async showDialog(params: SystemLogDetailDialogParams): Promise<void> {
|
||||||
this._params = params;
|
this._params = params;
|
||||||
|
this._manifest = undefined;
|
||||||
await this.updateComplete;
|
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 {
|
protected render(): TemplateResult {
|
||||||
if (!this._params) {
|
if (!this._params) {
|
||||||
return html``;
|
return html``;
|
||||||
@ -58,19 +73,30 @@ class DialogSystemLogDetail extends LitElement {
|
|||||||
${integration
|
${integration
|
||||||
? html`
|
? html`
|
||||||
<br />
|
<br />
|
||||||
Integration: ${domainToName(this.hass.localize, integration)}
|
Integration:
|
||||||
(<a
|
${this._manifest
|
||||||
href=${integrationDocsUrl(integration)}
|
? this._manifest.name
|
||||||
target="_blank"
|
: domainToName(this.hass.localize, integration)}
|
||||||
rel="noreferrer"
|
${!this._manifest ||
|
||||||
>documentation</a
|
// Can happen with custom integrations
|
||||||
>,
|
!this._manifest.documentation
|
||||||
<a
|
? ""
|
||||||
href=${integrationIssuesUrl(integration)}
|
: html`
|
||||||
target="_blank"
|
(<a
|
||||||
rel="noreferrer"
|
href=${this._manifest.documentation}
|
||||||
>issues</a
|
target="_blank"
|
||||||
>)
|
rel="noreferrer"
|
||||||
|
>documentation</a
|
||||||
|
>${!this._manifest.is_built_in
|
||||||
|
? ""
|
||||||
|
: html`,
|
||||||
|
<a
|
||||||
|
href=${integrationIssuesUrl(integration)}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>issues</a
|
||||||
|
>`})
|
||||||
|
`}
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
<br />
|
<br />
|
||||||
@ -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<boolean>): void {
|
private _openedChanged(ev: PolymerChangedEvent<boolean>): void {
|
||||||
if (!(ev.detail as any).value) {
|
if (!(ev.detail as any).value) {
|
||||||
this._params = undefined;
|
this._params = undefined;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user