mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-22 16:56:35 +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 { 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<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) =>
|
||||
item.name.startsWith("homeassistant.components.")
|
||||
? item.name.split(".")[2]
|
||||
: item.name.startsWith("custom_components.")
|
||||
? item.name.split(".")[1]
|
||||
: undefined;
|
||||
|
@ -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`
|
||||
<ha-card header="Integrations">
|
||||
<table class="card-content">
|
||||
<tbody>
|
||||
${this._sortedIntegrations(this.hass!.config.components).map(
|
||||
(domain) => html`
|
||||
<tr>
|
||||
<td>
|
||||
<img
|
||||
loading="lazy"
|
||||
src="https://brands.home-assistant.io/_/${domain}/icon.png"
|
||||
referrerpolicy="no-referrer"
|
||||
/>
|
||||
</td>
|
||||
<td>${domain}</td>
|
||||
<td>
|
||||
<a
|
||||
href=${integrationDocsUrl(domain)}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Documentation
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a
|
||||
href=${integrationIssuesUrl(domain)}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Issues
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
`
|
||||
(domain) => {
|
||||
const manifest = this._manifests && this._manifests[domain];
|
||||
return html`
|
||||
<tr>
|
||||
<td>
|
||||
<img
|
||||
loading="lazy"
|
||||
src="https://brands.home-assistant.io/_/${domain}/icon.png"
|
||||
referrerpolicy="no-referrer"
|
||||
/>
|
||||
</td>
|
||||
<td class="name">
|
||||
${manifest?.name}<br />
|
||||
<span class="domain">${domain}</span>
|
||||
</td>
|
||||
${!manifest
|
||||
? ""
|
||||
: html`
|
||||
<td>
|
||||
<a
|
||||
href=${manifest.documentation}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Documentation
|
||||
</a>
|
||||
</td>
|
||||
${!manifest.is_built_in
|
||||
? ""
|
||||
: html`
|
||||
<td>
|
||||
<a
|
||||
href=${integrationIssuesUrl(domain)}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Issues
|
||||
</a>
|
||||
</td>
|
||||
`}
|
||||
`}
|
||||
</tr>
|
||||
`;
|
||||
}
|
||||
)}
|
||||
</tbody>
|
||||
</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 {
|
||||
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);
|
||||
|
@ -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<void> {
|
||||
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`
|
||||
<br />
|
||||
Integration: ${domainToName(this.hass.localize, integration)}
|
||||
(<a
|
||||
href=${integrationDocsUrl(integration)}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>documentation</a
|
||||
>,
|
||||
<a
|
||||
href=${integrationIssuesUrl(integration)}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>issues</a
|
||||
>)
|
||||
Integration:
|
||||
${this._manifest
|
||||
? this._manifest.name
|
||||
: domainToName(this.hass.localize, integration)}
|
||||
${!this._manifest ||
|
||||
// Can happen with custom integrations
|
||||
!this._manifest.documentation
|
||||
? ""
|
||||
: html`
|
||||
(<a
|
||||
href=${this._manifest.documentation}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>documentation</a
|
||||
>${!this._manifest.is_built_in
|
||||
? ""
|
||||
: html`,
|
||||
<a
|
||||
href=${integrationIssuesUrl(integration)}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>issues</a
|
||||
>`})
|
||||
`}
|
||||
`
|
||||
: ""}
|
||||
<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 {
|
||||
if (!(ev.detail as any).value) {
|
||||
this._params = undefined;
|
||||
|
Loading…
x
Reference in New Issue
Block a user