254 lines
7.2 KiB
TypeScript
254 lines
7.2 KiB
TypeScript
import "@polymer/paper-item/paper-item";
|
|
import "@polymer/paper-listbox/paper-listbox";
|
|
import {
|
|
css,
|
|
CSSResult,
|
|
customElement,
|
|
html,
|
|
LitElement,
|
|
property,
|
|
TemplateResult,
|
|
} from "lit-element";
|
|
import { supportsFeature } from "../../../common/entity/supports-feature";
|
|
import "../../../components/ha-attributes";
|
|
import "../../../components/ha-icon";
|
|
import "../../../components/ha-icon-button";
|
|
import "../../../components/ha-paper-dropdown-menu";
|
|
import {
|
|
VacuumEntity,
|
|
VACUUM_SUPPORT_BATTERY,
|
|
VACUUM_SUPPORT_CLEAN_SPOT,
|
|
VACUUM_SUPPORT_FAN_SPEED,
|
|
VACUUM_SUPPORT_LOCATE,
|
|
VACUUM_SUPPORT_PAUSE,
|
|
VACUUM_SUPPORT_RETURN_HOME,
|
|
VACUUM_SUPPORT_START,
|
|
VACUUM_SUPPORT_STATUS,
|
|
VACUUM_SUPPORT_STOP,
|
|
} from "../../../data/vacuum";
|
|
import { HomeAssistant } from "../../../types";
|
|
|
|
interface VacuumCommand {
|
|
translationKey: string;
|
|
icon: string;
|
|
serviceName: string;
|
|
isVisible: (stateObj: VacuumEntity) => boolean;
|
|
}
|
|
|
|
const VACUUM_COMMANDS: VacuumCommand[] = [
|
|
{
|
|
translationKey: "start",
|
|
icon: "hass:play",
|
|
serviceName: "start",
|
|
isVisible: (stateObj) => supportsFeature(stateObj, VACUUM_SUPPORT_START),
|
|
},
|
|
{
|
|
translationKey: "pause",
|
|
icon: "hass:pause",
|
|
serviceName: "pause",
|
|
isVisible: (stateObj) =>
|
|
// We need also to check if Start is supported because if not we show play-pause
|
|
supportsFeature(stateObj, VACUUM_SUPPORT_START) &&
|
|
supportsFeature(stateObj, VACUUM_SUPPORT_PAUSE),
|
|
},
|
|
{
|
|
translationKey: "start_pause",
|
|
icon: "hass:play-pause",
|
|
serviceName: "start_pause",
|
|
isVisible: (stateObj) =>
|
|
// If start is supported, we don't show this button
|
|
!supportsFeature(stateObj, VACUUM_SUPPORT_START) &&
|
|
supportsFeature(stateObj, VACUUM_SUPPORT_PAUSE),
|
|
},
|
|
{
|
|
translationKey: "stop",
|
|
icon: "hass:stop",
|
|
serviceName: "stop",
|
|
isVisible: (stateObj) => supportsFeature(stateObj, VACUUM_SUPPORT_STOP),
|
|
},
|
|
{
|
|
translationKey: "clean_spot",
|
|
icon: "hass:target-variant",
|
|
serviceName: "clean_spot",
|
|
isVisible: (stateObj) =>
|
|
supportsFeature(stateObj, VACUUM_SUPPORT_CLEAN_SPOT),
|
|
},
|
|
{
|
|
translationKey: "locate",
|
|
icon: "hass:map-marker",
|
|
serviceName: "locate",
|
|
isVisible: (stateObj) => supportsFeature(stateObj, VACUUM_SUPPORT_LOCATE),
|
|
},
|
|
{
|
|
translationKey: "return_home",
|
|
icon: "hass:home-map-marker",
|
|
serviceName: "return_to_base",
|
|
isVisible: (stateObj) =>
|
|
supportsFeature(stateObj, VACUUM_SUPPORT_RETURN_HOME),
|
|
},
|
|
];
|
|
|
|
@customElement("more-info-vacuum")
|
|
class MoreInfoVacuum extends LitElement {
|
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
|
|
|
@property() public stateObj?: VacuumEntity;
|
|
|
|
protected render(): TemplateResult {
|
|
if (!this.hass || !this.stateObj) {
|
|
return html``;
|
|
}
|
|
|
|
const stateObj = this.stateObj;
|
|
|
|
const filterExtraAttributes =
|
|
"fan_speed,fan_speed_list,status,battery_level,battery_icon";
|
|
|
|
return html`
|
|
<div class="flex-horizontal">
|
|
${supportsFeature(stateObj, VACUUM_SUPPORT_STATUS)
|
|
? html`
|
|
<div>
|
|
<span class="status-subtitle"
|
|
>${this.hass!.localize(
|
|
"ui.dialogs.more_info_control.vacuum.status"
|
|
)}:
|
|
</span>
|
|
<span><strong>${stateObj.attributes.status}</strong></span>
|
|
</div>
|
|
`
|
|
: ""}
|
|
${supportsFeature(stateObj, VACUUM_SUPPORT_BATTERY)
|
|
? html`
|
|
<div>
|
|
<span>
|
|
<ha-icon .icon=${stateObj.attributes.battery_icon}></ha-icon>
|
|
${stateObj.attributes.battery_level} %
|
|
</span>
|
|
</div>
|
|
`
|
|
: ""}
|
|
</div>
|
|
|
|
${VACUUM_COMMANDS.some((item) => item.isVisible(stateObj))
|
|
? html`
|
|
<div>
|
|
<p></p>
|
|
<div class="status-subtitle">
|
|
${this.hass!.localize(
|
|
"ui.dialogs.more_info_control.vacuum.commands"
|
|
)}
|
|
</div>
|
|
<div class="flex-horizontal">
|
|
${VACUUM_COMMANDS.filter((item) =>
|
|
item.isVisible(stateObj)
|
|
).map(
|
|
(item) => html`
|
|
<div>
|
|
<ha-icon-button
|
|
.icon=${item.icon}
|
|
.entry=${item}
|
|
@click=${this.callService}
|
|
.title=${this.hass!.localize(
|
|
`ui.dialogs.more_info_control.vacuum.${item.translationKey}`
|
|
)}
|
|
></ha-icon-button>
|
|
</div>
|
|
`
|
|
)}
|
|
</div>
|
|
</div>
|
|
`
|
|
: ""}
|
|
${supportsFeature(stateObj, VACUUM_SUPPORT_FAN_SPEED)
|
|
? html`
|
|
<div>
|
|
<div class="flex-horizontal">
|
|
<ha-paper-dropdown-menu
|
|
.label=${this.hass!.localize(
|
|
"ui.dialogs.more_info_control.vacuum.fan_speed"
|
|
)}
|
|
>
|
|
<paper-listbox
|
|
slot="dropdown-content"
|
|
.selected=${stateObj.attributes.fan_speed}
|
|
@iron-select=${this.handleFanSpeedChanged}
|
|
attr-for-selected="item-name"
|
|
>
|
|
${stateObj.attributes.fan_speed_list!.map(
|
|
(mode) => html`
|
|
<paper-item .itemName=${mode}>
|
|
${mode}
|
|
</paper-item>
|
|
`
|
|
)}
|
|
</paper-listbox>
|
|
</ha-paper-dropdown-menu>
|
|
<div
|
|
style="justify-content: center; align-self: center; padding-top: 1.3em"
|
|
>
|
|
<span>
|
|
<ha-icon icon="hass:fan"></ha-icon>
|
|
${stateObj.attributes.fan_speed}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<p></p>
|
|
</div>
|
|
`
|
|
: ""}
|
|
|
|
<ha-attributes
|
|
.stateObj=${this.stateObj}
|
|
.extraFilters=${filterExtraAttributes}
|
|
></ha-attributes>
|
|
`;
|
|
}
|
|
|
|
private callService(ev: CustomEvent) {
|
|
const entry = (ev.target! as any).entry as VacuumCommand;
|
|
this.hass.callService("vacuum", entry.serviceName, {
|
|
entity_id: this.stateObj!.entity_id,
|
|
});
|
|
}
|
|
|
|
private handleFanSpeedChanged(ev: CustomEvent) {
|
|
const oldVal = this.stateObj!.attributes.fan_speed;
|
|
const newVal = ev.detail.item.itemName;
|
|
|
|
if (!newVal || oldVal === newVal) {
|
|
return;
|
|
}
|
|
|
|
this.hass.callService("vacuum", "set_fan_speed", {
|
|
entity_id: this.stateObj!.entity_id,
|
|
fan_speed: newVal,
|
|
});
|
|
}
|
|
|
|
static get styles(): CSSResult {
|
|
return css`
|
|
:host {
|
|
line-height: 1.5;
|
|
}
|
|
.status-subtitle {
|
|
color: var(--secondary-text-color);
|
|
}
|
|
paper-item {
|
|
cursor: pointer;
|
|
}
|
|
.flex-horizontal {
|
|
display: flex;
|
|
flex-direction: row;
|
|
justify-content: space-between;
|
|
}
|
|
`;
|
|
}
|
|
}
|
|
|
|
declare global {
|
|
interface HTMLElementTagNameMap {
|
|
"more-info-vacuum": MoreInfoVacuum;
|
|
}
|
|
}
|