201 lines
6.0 KiB
TypeScript
Executable File
201 lines
6.0 KiB
TypeScript
Executable File
import { mdiClose } from "@mdi/js";
|
|
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
|
import { customElement, property, state } from "lit/decorators";
|
|
import memoizeOne from "memoize-one";
|
|
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
|
import "../../../../src/common/search/search-input";
|
|
import { stringCompare } from "../../../../src/common/string/compare";
|
|
import "../../../../src/components/ha-dialog";
|
|
import "../../../../src/components/ha-expansion-panel";
|
|
import "../../../../src/components/ha-icon-button";
|
|
import { HassioHardwareInfo } from "../../../../src/data/hassio/hardware";
|
|
import { dump } from "../../../../src/resources/js-yaml-dump";
|
|
import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
|
|
import { HomeAssistant } from "../../../../src/types";
|
|
import { HassioHardwareDialogParams } from "./show-dialog-hassio-hardware";
|
|
|
|
const _filterDevices = memoizeOne(
|
|
(showAdvanced: boolean, hardware: HassioHardwareInfo, filter: string) =>
|
|
hardware.devices
|
|
.filter(
|
|
(device) =>
|
|
(showAdvanced ||
|
|
["tty", "gpio", "input"].includes(device.subsystem)) &&
|
|
(device.by_id?.toLowerCase().includes(filter) ||
|
|
device.name.toLowerCase().includes(filter) ||
|
|
device.dev_path.toLocaleLowerCase().includes(filter) ||
|
|
JSON.stringify(device.attributes)
|
|
.toLocaleLowerCase()
|
|
.includes(filter))
|
|
)
|
|
.sort((a, b) => stringCompare(a.name, b.name))
|
|
);
|
|
|
|
@customElement("dialog-hassio-hardware")
|
|
class HassioHardwareDialog extends LitElement {
|
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
|
|
|
@state() private _dialogParams?: HassioHardwareDialogParams;
|
|
|
|
@state() private _filter?: string;
|
|
|
|
public showDialog(dialogParams: HassioHardwareDialogParams) {
|
|
this._dialogParams = dialogParams;
|
|
}
|
|
|
|
public closeDialog() {
|
|
this._dialogParams = undefined;
|
|
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
|
}
|
|
|
|
protected render(): TemplateResult {
|
|
if (!this._dialogParams) {
|
|
return html``;
|
|
}
|
|
|
|
const devices = _filterDevices(
|
|
this.hass.userData?.showAdvanced || false,
|
|
this._dialogParams.hardware,
|
|
(this._filter || "").toLowerCase()
|
|
);
|
|
|
|
return html`
|
|
<ha-dialog
|
|
open
|
|
scrimClickAction
|
|
hideActions
|
|
@closed=${this.closeDialog}
|
|
.heading=${this._dialogParams.supervisor.localize(
|
|
"dialog.hardware.title"
|
|
)}
|
|
>
|
|
<div class="header" slot="heading">
|
|
<h2>
|
|
${this._dialogParams.supervisor.localize("dialog.hardware.title")}
|
|
</h2>
|
|
<ha-icon-button
|
|
.label=${this._dialogParams.supervisor.localize("common.close")}
|
|
.path=${mdiClose}
|
|
dialogAction="close"
|
|
></ha-icon-button>
|
|
<search-input
|
|
.hass=${this.hass}
|
|
autofocus
|
|
no-label-float
|
|
.filter=${this._filter}
|
|
@value-changed=${this._handleSearchChange}
|
|
.label=${this._dialogParams.supervisor.localize(
|
|
"dialog.hardware.search"
|
|
)}
|
|
>
|
|
</search-input>
|
|
</div>
|
|
|
|
${devices.map(
|
|
(device) =>
|
|
html`<ha-expansion-panel
|
|
.header=${device.name}
|
|
.secondary=${device.by_id || undefined}
|
|
outlined
|
|
>
|
|
<div class="device-property">
|
|
<span>
|
|
${this._dialogParams!.supervisor.localize(
|
|
"dialog.hardware.subsystem"
|
|
)}:
|
|
</span>
|
|
<span>${device.subsystem}</span>
|
|
</div>
|
|
<div class="device-property">
|
|
<span>
|
|
${this._dialogParams!.supervisor.localize(
|
|
"dialog.hardware.device_path"
|
|
)}:
|
|
</span>
|
|
<code>${device.dev_path}</code>
|
|
</div>
|
|
${device.by_id
|
|
? html` <div class="device-property">
|
|
<span>
|
|
${this._dialogParams!.supervisor.localize(
|
|
"dialog.hardware.id"
|
|
)}:
|
|
</span>
|
|
<code>${device.by_id}</code>
|
|
</div>`
|
|
: ""}
|
|
<div class="attributes">
|
|
<span>
|
|
${this._dialogParams!.supervisor.localize(
|
|
"dialog.hardware.attributes"
|
|
)}:
|
|
</span>
|
|
<pre>${dump(device.attributes, { indent: 2 })}</pre>
|
|
</div>
|
|
</ha-expansion-panel>`
|
|
)}
|
|
</ha-dialog>
|
|
`;
|
|
}
|
|
|
|
private _handleSearchChange(ev: CustomEvent) {
|
|
this._filter = ev.detail.value;
|
|
}
|
|
|
|
static get styles(): CSSResultGroup {
|
|
return [
|
|
haStyle,
|
|
haStyleDialog,
|
|
css`
|
|
ha-icon-button {
|
|
position: absolute;
|
|
right: 16px;
|
|
top: 10px;
|
|
text-decoration: none;
|
|
color: var(--primary-text-color);
|
|
}
|
|
h2 {
|
|
margin: 18px 42px 0 18px;
|
|
color: var(--primary-text-color);
|
|
}
|
|
|
|
ha-expansion-panel {
|
|
margin: 4px 0;
|
|
}
|
|
pre,
|
|
code {
|
|
background-color: var(--markdown-code-background-color, none);
|
|
border-radius: 3px;
|
|
}
|
|
pre {
|
|
padding: 16px;
|
|
overflow: auto;
|
|
line-height: 1.45;
|
|
font-family: var(--code-font-family, monospace);
|
|
}
|
|
code {
|
|
font-size: 85%;
|
|
padding: 0.2em 0.4em;
|
|
}
|
|
search-input {
|
|
margin: 0 16px;
|
|
display: block;
|
|
}
|
|
.device-property {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
}
|
|
.attributes {
|
|
margin-top: 12px;
|
|
}
|
|
`,
|
|
];
|
|
}
|
|
}
|
|
|
|
declare global {
|
|
interface HTMLElementTagNameMap {
|
|
"dialog-hassio-hardware": HassioHardwareDialog;
|
|
}
|
|
}
|