Add lozalization to more-info-vacuum (#4793)

* Convert more-info-vacuum to Lit

* Introduce VacuumCommand to reduce render complexity and duplicate code

* Add localization for more-info-vacuum

* Inline supportFeature instead of creating a const.

* - Use interface instead of class for VacuumCommand
- Add different translation for start_pause and pause as they are not the same

* fix typo

* Use VACUUM_COMMANDS.some instead of writing duplicate code

* add @bramkragten suggestions
This commit is contained in:
Robert Resch 2020-02-11 09:15:38 +01:00 committed by GitHub
parent d052b9ede8
commit 9fce60065b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 290 additions and 263 deletions

22
src/data/vacuum.ts Normal file
View File

@ -0,0 +1,22 @@
import {
HassEntityAttributeBase,
HassEntityBase,
} from "home-assistant-js-websocket";
export const VACUUM_SUPPORT_PAUSE = 4;
export const VACUUM_SUPPORT_STOP = 8;
export const VACUUM_SUPPORT_RETURN_HOME = 16;
export const VACUUM_SUPPORT_FAN_SPEED = 32;
export const VACUUM_SUPPORT_BATTERY = 64;
export const VACUUM_SUPPORT_STATUS = 128;
export const VACUUM_SUPPORT_LOCATE = 512;
export const VACUUM_SUPPORT_CLEAN_SPOT = 1024;
export const VACUUM_SUPPORT_START = 8192;
export type VacuumEntity = HassEntityBase & {
attributes: HassEntityAttributeBase & {
battery_level: number;
fan_speed: any;
[key: string]: any;
};
};

View File

@ -1,263 +0,0 @@
import "@polymer/iron-flex-layout/iron-flex-layout-classes";
import "@polymer/iron-icon/iron-icon";
import "@polymer/paper-icon-button/paper-icon-button";
import "@polymer/paper-item/paper-item";
import "@polymer/paper-listbox/paper-listbox";
import { html } from "@polymer/polymer/lib/utils/html-tag";
import { PolymerElement } from "@polymer/polymer/polymer-element";
import "../../../components/ha-attributes";
import "../../../components/ha-paper-dropdown-menu";
import { supportsFeature } from "../../../common/entity/supports-feature";
class MoreInfoVacuum extends PolymerElement {
static get template() {
return html`
<style include="iron-flex iron-flex-alignment"></style>
<style>
:host {
@apply --paper-font-body1;
line-height: 1.5;
}
.status-subtitle {
color: var(--secondary-text-color);
}
paper-item {
cursor: pointer;
}
</style>
<div class="horizontal justified layout">
<div hidden$="[[!supportsStatus(stateObj)]]">
<span class="status-subtitle">Status: </span
><span><strong>[[stateObj.attributes.status]]</strong></span>
</div>
<div hidden$="[[!supportsBattery(stateObj)]]">
<span
><iron-icon icon="[[stateObj.attributes.battery_icon]]"></iron-icon>
[[stateObj.attributes.battery_level]] %</span
>
</div>
</div>
<div hidden$="[[!supportsCommandBar(stateObj)]]">
<p></p>
<div class="status-subtitle">Vacuum cleaner commands:</div>
<div class="horizontal justified layout">
<template is="dom-if" if="[[supportsStart(stateObj)]]">
<div>
<paper-icon-button
icon="hass:play"
on-click="onStart"
title="Start"
></paper-icon-button>
</div>
<div hidden$="[[!supportsPause(stateObj)]]">
<paper-icon-button
icon="hass:pause"
on-click="onPause"
title="Pause"
></paper-icon-button>
</div>
</template>
<template is="dom-if" if="[[!supportsStart(stateObj)]]">
<div hidden$="[[!supportsPause(stateObj)]]">
<paper-icon-button
icon="hass:play-pause"
on-click="onPlayPause"
title="Pause"
></paper-icon-button>
</div>
</template>
<div hidden$="[[!supportsStop(stateObj)]]">
<paper-icon-button
icon="hass:stop"
on-click="onStop"
title="Stop"
></paper-icon-button>
</div>
<div hidden$="[[!supportsCleanSpot(stateObj)]]">
<paper-icon-button
icon="hass:broom"
on-click="onCleanSpot"
title="Clean spot"
></paper-icon-button>
</div>
<div hidden$="[[!supportsLocate(stateObj)]]">
<paper-icon-button
icon="hass:map-marker"
on-click="onLocate"
title="Locate"
></paper-icon-button>
</div>
<div hidden$="[[!supportsReturnHome(stateObj)]]">
<paper-icon-button
icon="hass:home-map-marker"
on-click="onReturnHome"
title="Return home"
></paper-icon-button>
</div>
</div>
</div>
<div hidden$="[[!supportsFanSpeed(stateObj)]]">
<div class="horizontal justified layout">
<ha-paper-dropdown-menu
label-float=""
dynamic-align=""
label="Fan speed"
>
<paper-listbox
slot="dropdown-content"
selected="[[stateObj.attributes.fan_speed]]"
on-selected-changed="fanSpeedChanged"
attr-for-selected="item-name"
>
<template
is="dom-repeat"
items="[[stateObj.attributes.fan_speed_list]]"
>
<paper-item item-name$="[[item]]">[[item]]</paper-item>
</template>
</paper-listbox>
</ha-paper-dropdown-menu>
<div
style="justify-content: center; align-self: center; padding-top: 1.3em"
>
<span
><iron-icon icon="hass:fan"></iron-icon>
[[stateObj.attributes.fan_speed]]</span
>
</div>
</div>
<p></p>
</div>
<ha-attributes
state-obj="[[stateObj]]"
extra-filters="fan_speed,fan_speed_list,status,battery_level,battery_icon"
></ha-attributes>
`;
}
static get properties() {
return {
hass: {
type: Object,
},
inDialog: {
type: Boolean,
value: false,
},
stateObj: {
type: Object,
},
};
}
supportsPause(stateObj) {
return supportsFeature(stateObj, 4);
}
supportsStop(stateObj) {
return supportsFeature(stateObj, 8);
}
supportsReturnHome(stateObj) {
return supportsFeature(stateObj, 16);
}
supportsFanSpeed(stateObj) {
return supportsFeature(stateObj, 32);
}
supportsBattery(stateObj) {
return supportsFeature(stateObj, 64);
}
supportsStatus(stateObj) {
return supportsFeature(stateObj, 128);
}
supportsLocate(stateObj) {
return supportsFeature(stateObj, 512);
}
supportsCleanSpot(stateObj) {
return supportsFeature(stateObj, 1024);
}
supportsStart(stateObj) {
return supportsFeature(stateObj, 8192);
}
supportsCommandBar(stateObj) {
return (
supportsFeature(stateObj, 4) |
supportsFeature(stateObj, 8) |
supportsFeature(stateObj, 16) |
supportsFeature(stateObj, 512) |
supportsFeature(stateObj, 1024) |
supportsFeature(stateObj, 8192)
);
}
fanSpeedChanged(ev) {
var oldVal = this.stateObj.attributes.fan_speed;
var newVal = ev.detail.value;
if (!newVal || oldVal === newVal) return;
this.hass.callService("vacuum", "set_fan_speed", {
entity_id: this.stateObj.entity_id,
fan_speed: newVal,
});
}
onStop() {
this.hass.callService("vacuum", "stop", {
entity_id: this.stateObj.entity_id,
});
}
onPlayPause() {
this.hass.callService("vacuum", "start_pause", {
entity_id: this.stateObj.entity_id,
});
}
onPause() {
this.hass.callService("vacuum", "pause", {
entity_id: this.stateObj.entity_id,
});
}
onStart() {
this.hass.callService("vacuum", "start", {
entity_id: this.stateObj.entity_id,
});
}
onLocate() {
this.hass.callService("vacuum", "locate", {
entity_id: this.stateObj.entity_id,
});
}
onCleanSpot() {
this.hass.callService("vacuum", "clean_spot", {
entity_id: this.stateObj.entity_id,
});
}
onReturnHome() {
this.hass.callService("vacuum", "return_to_base", {
entity_id: this.stateObj.entity_id,
});
}
}
customElements.define("more-info-vacuum", MoreInfoVacuum);

View File

@ -0,0 +1,256 @@
import "@polymer/iron-icon/iron-icon";
import "@polymer/paper-icon-button/paper-icon-button";
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 { HomeAssistant } from "../../../types";
import "../../../components/ha-paper-dropdown-menu";
import "../../../components/ha-attributes";
import {
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,
VacuumEntity,
} from "../../../data/vacuum";
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:broom",
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() 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>
<iron-icon .icon=${stateObj.attributes.battery_icon}></iron-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>
<paper-icon-button
.icon=${item.icon}
.entry=${item}
@click=${this.callService}
.title=${this.hass!.localize(
`ui.dialogs.more_info_control.vacuum.${item.translationKey}`
)}
></paper-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>
<iron-icon icon="hass:fan"></iron-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 {
@apply --paper-font-body1;
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;
}
}

View File

@ -618,6 +618,18 @@
"remove_action": "Remove entity",
"confirm_remove_title": "Remove entity?",
"confirm_remove_text": "Are you sure you want to remove this entity?"
},
"vacuum": {
"status": "Status",
"commands": "Vacuum cleaner commands:",
"fan_speed": "Fan speed",
"start": "Start",
"pause": "Pause",
"stop": "Stop",
"clean_spot": "Clean spot",
"locate": "Locate",
"return_home": "Return home",
"start_pause": "Start/Pause"
}
},
"entity_registry": {