208 lines
5.7 KiB
TypeScript
208 lines
5.7 KiB
TypeScript
|
import {LitElement, html, css, customElement, property, TemplateResult, CSSResult} from "lit-element";
|
||
|
import {classMap} from "lit-html/directives/class-map";
|
||
|
|
||
|
import {HomeAssistant} from "./home-assistant-interface";
|
||
|
|
||
|
|
||
|
@customElement("room-glance-card")
|
||
|
export class RoomGlanceCard extends LitElement {
|
||
|
|
||
|
@property() public hass?: HomeAssistant;
|
||
|
@property() private _config?: any;
|
||
|
|
||
|
|
||
|
public setConfig(config: any) {
|
||
|
//if (!config || !config.entity) {
|
||
|
// throw new Error("Invalid configuration");
|
||
|
//}
|
||
|
console.log("Setting config", config);
|
||
|
this._config = config;
|
||
|
}
|
||
|
|
||
|
|
||
|
public static getCardSize(): number {
|
||
|
return 3;
|
||
|
}
|
||
|
|
||
|
|
||
|
protected render(): TemplateResult | void {
|
||
|
return html`
|
||
|
<ha-card>
|
||
|
<hui-image
|
||
|
class="${classMap({
|
||
|
clickable: true,
|
||
|
})}"
|
||
|
@ha-click="${this._handleTap}"
|
||
|
@ha-hold="${this._handleHold}"
|
||
|
.hass="${this.hass}"
|
||
|
image="${this._config.image}"
|
||
|
aspectRatio="${this._config.aspect_ratio}"
|
||
|
></hui-image>
|
||
|
|
||
|
<div class="box box-upper">
|
||
|
<div>${this._config.name}</div>
|
||
|
<div>
|
||
|
${this.renderCoverControl()}
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<div class="box box-lower">
|
||
|
<div class="title"></div>
|
||
|
<div>
|
||
|
${this._config.scenes.map( (sceneButtonCfg) => this.renderSceneButton(sceneButtonCfg))}
|
||
|
|
||
|
<paper-icon-button
|
||
|
icon="mdi:close-circle"
|
||
|
@click=${this.serviceHandler("light", "turn_off")}
|
||
|
></paper-icon-button>
|
||
|
|
||
|
<paper-icon-button
|
||
|
icon="mdi:chevron-up"
|
||
|
title="Heller"
|
||
|
@click=${this.serviceHandler("dimmer", "dim", {offset: 30})}
|
||
|
></paper-icon-button>
|
||
|
<paper-icon-button
|
||
|
icon="mdi:chevron-down"
|
||
|
title="Dunkler"
|
||
|
@click=${this.serviceHandler("dimmer", "dim", {offset: -30})}
|
||
|
></paper-icon-button>
|
||
|
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
|
||
|
|
||
|
</ha-card>
|
||
|
`;
|
||
|
}
|
||
|
|
||
|
private renderSceneButton(buttonCfg: any) {
|
||
|
return html`
|
||
|
<paper-icon-button
|
||
|
icon="${buttonCfg.icon || "mdi:checkbox-blank"}"
|
||
|
style="color: ${buttonCfg.color || ""};"
|
||
|
title="${buttonCfg.name}"
|
||
|
@click=${this.serviceHandler("scene", "turn_on", {entity_id: buttonCfg.scene})}
|
||
|
></paper-icon-button>
|
||
|
`;
|
||
|
}
|
||
|
|
||
|
private renderCoverControl() {
|
||
|
return html`
|
||
|
<paper-icon-button
|
||
|
icon="hass:menu"
|
||
|
@click=${this.serviceHandler("cover_half", "set_half")}
|
||
|
></paper-icon-button>
|
||
|
<paper-icon-button
|
||
|
icon="hass:arrow-up"
|
||
|
@click=${this.serviceHandler("cover", "open_cover")}
|
||
|
></paper-icon-button>
|
||
|
<paper-icon-button
|
||
|
icon="hass:stop"
|
||
|
@click=${this.serviceHandler("cover", "stop_cover")}
|
||
|
></paper-icon-button>
|
||
|
<paper-icon-button
|
||
|
icon="hass:arrow-down"
|
||
|
@click=${this.serviceHandler("cover", "close_cover")}
|
||
|
></paper-icon-button>
|
||
|
`;
|
||
|
}
|
||
|
|
||
|
private serviceHandler(domain: string, service: string, serviceData: { [key: string]: any } = {})
|
||
|
{
|
||
|
const thisObj = this;
|
||
|
return function(ev) {
|
||
|
ev.stopPropagation();
|
||
|
thisObj.callServiceForAllEntities(domain, service, serviceData);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private callServiceForAllEntities(domain: string, service:string, serviceData: { [key: string]: any } = {}) {
|
||
|
|
||
|
if (!serviceData.hasOwnProperty('entity_id')) {
|
||
|
for (let entity_id of this._config!.entities) {
|
||
|
serviceData['entity_id'] = entity_id;
|
||
|
console.log("Calling service", domain, service, serviceData);
|
||
|
this.hass!.callService(domain, service, serviceData);
|
||
|
}
|
||
|
} else {
|
||
|
console.log("Calling service with given entity_id", domain, service, serviceData);
|
||
|
this.hass!.callService(domain, service, serviceData);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private _handleTap() {
|
||
|
console.log("Image tap");
|
||
|
}
|
||
|
|
||
|
private _handleHold() {
|
||
|
console.log("Image hold");
|
||
|
}
|
||
|
|
||
|
|
||
|
static get styles(): CSSResult {
|
||
|
return css`
|
||
|
ha-card {
|
||
|
position: relative;
|
||
|
min-height: 48px;
|
||
|
overflow: hidden;
|
||
|
}
|
||
|
|
||
|
hui-image.clickable {
|
||
|
cursor: pointer;
|
||
|
}
|
||
|
|
||
|
.box {
|
||
|
/* start paper-font-common-nowrap style */
|
||
|
white-space: nowrap;
|
||
|
overflow: hidden;
|
||
|
text-overflow: ellipsis;
|
||
|
/* end paper-font-common-nowrap style */
|
||
|
|
||
|
position: absolute;
|
||
|
left: 0;
|
||
|
right: 0;
|
||
|
|
||
|
padding-left: 8px;
|
||
|
padding-right: 8px;
|
||
|
|
||
|
font-size: 16px;
|
||
|
line-height: 40px;
|
||
|
color: white;
|
||
|
display: flex;
|
||
|
justify-content: space-between;
|
||
|
background-color: rgba(0, 0, 0, 0.3);
|
||
|
}
|
||
|
|
||
|
.box-upper {
|
||
|
|
||
|
bottom: 45px;
|
||
|
padding-top: 4px;
|
||
|
padding-bottom: 0;
|
||
|
}
|
||
|
.box-lower {
|
||
|
bottom: 0;
|
||
|
padding-top: 0;
|
||
|
padding-bottom: 0px;
|
||
|
height:45px;
|
||
|
}
|
||
|
|
||
|
.box .title {
|
||
|
font-weight: 500;
|
||
|
margin-left: 8px;
|
||
|
}
|
||
|
|
||
|
ha-icon {
|
||
|
cursor: pointer;
|
||
|
padding: 8px;
|
||
|
color: #a9a9a9;
|
||
|
}
|
||
|
|
||
|
ha-icon.state-on {
|
||
|
color: white;
|
||
|
}
|
||
|
`;
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|