mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-18 23:06:40 +00:00
Add add-on selector/picker (#8422)
This commit is contained in:
parent
f5fb6c1e03
commit
54a2b2534a
148
src/components/ha-addon-picker.ts
Normal file
148
src/components/ha-addon-picker.ts
Normal file
@ -0,0 +1,148 @@
|
||||
import {
|
||||
customElement,
|
||||
html,
|
||||
internalProperty,
|
||||
LitElement,
|
||||
property,
|
||||
query,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { isComponentLoaded } from "../common/config/is_component_loaded";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import { compare } from "../common/string/compare";
|
||||
import { HassioAddonInfo } from "../data/hassio/addon";
|
||||
import { fetchHassioSupervisorInfo } from "../data/hassio/supervisor";
|
||||
import { showAlertDialog } from "../dialogs/generic/show-dialog-box";
|
||||
import { PolymerChangedEvent } from "../polymer-types";
|
||||
import { HomeAssistant } from "../types";
|
||||
import { HaComboBox } from "./ha-combo-box";
|
||||
|
||||
const rowRenderer = (
|
||||
root: HTMLElement,
|
||||
_owner,
|
||||
model: { item: HassioAddonInfo }
|
||||
) => {
|
||||
if (!root.firstElementChild) {
|
||||
root.innerHTML = `
|
||||
<style>
|
||||
paper-item {
|
||||
margin: -10px 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
<paper-item>
|
||||
<paper-item-body two-line="">
|
||||
<div class='name'>[[item.name]]</div>
|
||||
<div secondary>[[item.slug]]</div>
|
||||
</paper-item-body>
|
||||
</paper-item>
|
||||
`;
|
||||
}
|
||||
|
||||
root.querySelector(".name")!.textContent = model.item.name;
|
||||
root.querySelector("[secondary]")!.textContent = model.item.slug;
|
||||
};
|
||||
|
||||
@customElement("ha-addon-picker")
|
||||
class HaAddonPicker extends LitElement {
|
||||
public hass!: HomeAssistant;
|
||||
|
||||
@property() public label?: string;
|
||||
|
||||
@property() public value = "";
|
||||
|
||||
@internalProperty() private _addons?: HassioAddonInfo[];
|
||||
|
||||
@property({ type: Boolean }) public disabled = false;
|
||||
|
||||
@query("ha-combo-box") private _comboBox!: HaComboBox;
|
||||
|
||||
public open() {
|
||||
this._comboBox?.open();
|
||||
}
|
||||
|
||||
public focus() {
|
||||
this._comboBox?.focus();
|
||||
}
|
||||
|
||||
protected firstUpdated() {
|
||||
this._getAddons();
|
||||
}
|
||||
|
||||
protected render(): TemplateResult {
|
||||
if (!this._addons) {
|
||||
return html``;
|
||||
}
|
||||
return html`
|
||||
<ha-combo-box
|
||||
.hass=${this.hass}
|
||||
.label=${this.label === undefined && this.hass
|
||||
? this.hass.localize("ui.components.addon-picker.addon")
|
||||
: this.label}
|
||||
.value=${this._value}
|
||||
.renderer=${rowRenderer}
|
||||
.items=${this._addons}
|
||||
item-value-path="slug"
|
||||
item-id-path="slug"
|
||||
item-label-path="name"
|
||||
@value-changed=${this._addonChanged}
|
||||
></ha-combo-box>
|
||||
`;
|
||||
}
|
||||
|
||||
private async _getAddons() {
|
||||
try {
|
||||
if (isComponentLoaded(this.hass, "hassio")) {
|
||||
const supervisorInfo = await fetchHassioSupervisorInfo(this.hass);
|
||||
this._addons = supervisorInfo.addons.sort((a, b) =>
|
||||
compare(a.name, b.name)
|
||||
);
|
||||
} else {
|
||||
showAlertDialog(this, {
|
||||
title: this.hass.localize(
|
||||
"ui.componencts.addon-picker.error.no_supervisor.title"
|
||||
),
|
||||
text: this.hass.localize(
|
||||
"ui.componencts.addon-picker.error.no_supervisor.description"
|
||||
),
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
showAlertDialog(this, {
|
||||
title: this.hass.localize(
|
||||
"ui.componencts.addon-picker.error.fetch_addons.title"
|
||||
),
|
||||
text: this.hass.localize(
|
||||
"ui.componencts.addon-picker.error.fetch_addons.description"
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private get _value() {
|
||||
return this.value || "";
|
||||
}
|
||||
|
||||
private _addonChanged(ev: PolymerChangedEvent<string>) {
|
||||
ev.stopPropagation();
|
||||
const newValue = ev.detail.value;
|
||||
|
||||
if (newValue !== this._value) {
|
||||
this._setValue(newValue);
|
||||
}
|
||||
}
|
||||
|
||||
private _setValue(value: string) {
|
||||
this.value = value;
|
||||
setTimeout(() => {
|
||||
fireEvent(this, "value-changed", { value });
|
||||
fireEvent(this, "change");
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-addon-picker": HaAddonPicker;
|
||||
}
|
||||
}
|
30
src/components/ha-selector/ha-selector-addon.ts
Normal file
30
src/components/ha-selector/ha-selector-addon.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { customElement, html, LitElement, property } from "lit-element";
|
||||
import { AddonSelector } from "../../data/selector";
|
||||
import { HomeAssistant } from "../../types";
|
||||
import "../ha-addon-picker";
|
||||
|
||||
@customElement("ha-selector-addon")
|
||||
export class HaAddonSelector extends LitElement {
|
||||
@property() public hass!: HomeAssistant;
|
||||
|
||||
@property() public selector!: AddonSelector;
|
||||
|
||||
@property() public value?: any;
|
||||
|
||||
@property() public label?: string;
|
||||
|
||||
protected render() {
|
||||
return html`<ha-addon-picker
|
||||
.hass=${this.hass}
|
||||
.value=${this.value}
|
||||
.label=${this.label}
|
||||
allow-custom-entity
|
||||
></ha-addon-picker>`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-selector-addon": HaAddonSelector;
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ import { dynamicElement } from "../../common/dom/dynamic-element-directive";
|
||||
import { Selector } from "../../data/selector";
|
||||
import { HomeAssistant } from "../../types";
|
||||
import "./ha-selector-action";
|
||||
import "./ha-selector-addon";
|
||||
import "./ha-selector-area";
|
||||
import "./ha-selector-boolean";
|
||||
import "./ha-selector-device";
|
||||
|
@ -1,4 +1,5 @@
|
||||
export type Selector =
|
||||
| AddonSelector
|
||||
| EntitySelector
|
||||
| DeviceSelector
|
||||
| AreaSelector
|
||||
@ -30,6 +31,13 @@ export interface DeviceSelector {
|
||||
};
|
||||
}
|
||||
|
||||
export interface AddonSelector {
|
||||
addon: {
|
||||
name?: string;
|
||||
slug?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface AreaSelector {
|
||||
area: {
|
||||
entity?: {
|
||||
|
@ -382,6 +382,19 @@
|
||||
"failed_create_area": "Failed to create area."
|
||||
}
|
||||
},
|
||||
"addon-picker": {
|
||||
"addon": "Add-on",
|
||||
"error": {
|
||||
"no_supervisor": {
|
||||
"title": "No Supervisor",
|
||||
"description": "No Supervisor found, so add-ons could not be loaded."
|
||||
},
|
||||
"fetch_addons": {
|
||||
"title": "Error fetching add-ons",
|
||||
"description": "Fetching add-ons returned an error."
|
||||
}
|
||||
}
|
||||
},
|
||||
"picture-upload": {
|
||||
"label": "Picture",
|
||||
"unsupported_format": "Unsupported format, please choose a JPEG, PNG or GIF image."
|
||||
|
Loading…
x
Reference in New Issue
Block a user