Big restructuring - repo is now a full home assistant config directory
7
custom_frontend_sources/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
To install dependencies run:
|
||||
npm install
|
||||
|
||||
|
||||
To build:
|
||||
npm run build
|
||||
copy file from dist folder
|
||||
BIN
custom_frontend_sources/img/bedroom_16_9.jpg
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
custom_frontend_sources/img/living_area_16_9.jpg
Normal file
|
After Width: | Height: | Size: 548 KiB |
BIN
custom_frontend_sources/img/office_martin_16_9.jpg
Normal file
|
After Width: | Height: | Size: 977 KiB |
BIN
custom_frontend_sources/img/original/IMAG2504_BURST002_COVER.jpg
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
custom_frontend_sources/img/original/IMAG2505.jpg
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
custom_frontend_sources/img/original/IMAG2506.jpg
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
custom_frontend_sources/img/original/IMAG2507.jpg
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
custom_frontend_sources/img/original/IMAG2508.jpg
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
custom_frontend_sources/img/original/IMAG2551.jpg
Normal file
|
After Width: | Height: | Size: 2.1 MiB |
BIN
custom_frontend_sources/img/original/IMAG2552.jpg
Normal file
|
After Width: | Height: | Size: 2.0 MiB |
BIN
custom_frontend_sources/img/original/IMAG2553.jpg
Normal file
|
After Width: | Height: | Size: 2.0 MiB |
BIN
custom_frontend_sources/img/original/IMAG2554.jpg
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
custom_frontend_sources/img/original/IMAG2555.jpg
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
custom_frontend_sources/img/original/IMAG2556.jpg
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
custom_frontend_sources/img/original/IMAG2557.jpg
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
custom_frontend_sources/img/original/IMAG2558.jpg
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
custom_frontend_sources/img/original/IMAG2559.jpg
Normal file
|
After Width: | Height: | Size: 331 KiB |
BIN
custom_frontend_sources/img/original/IMAG2560.jpg
Normal file
|
After Width: | Height: | Size: 2.0 MiB |
BIN
custom_frontend_sources/img/original/IMAG2561.jpg
Normal file
|
After Width: | Height: | Size: 1.9 MiB |
BIN
custom_frontend_sources/img/original/IMAG2562.jpg
Normal file
|
After Width: | Height: | Size: 2.0 MiB |
BIN
custom_frontend_sources/img/original/IMAG2563.jpg
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
custom_frontend_sources/img/original/IMAG2564.jpg
Normal file
|
After Width: | Height: | Size: 2.1 MiB |
BIN
custom_frontend_sources/img/original/IMAG2565.jpg
Normal file
|
After Width: | Height: | Size: 2.0 MiB |
BIN
custom_frontend_sources/img/original/IMAG2567.jpg
Normal file
|
After Width: | Height: | Size: 1.9 MiB |
BIN
custom_frontend_sources/img/original/IMAG2568.jpg
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 3.0 MiB |
|
After Width: | Height: | Size: 2.3 MiB |
308
custom_frontend_sources/room-glance-card/dist/room-glance-card.js
vendored
Normal file
4606
custom_frontend_sources/room-glance-card/package-lock.json
generated
Normal file
21
custom_frontend_sources/room-glance-card/package.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "state-card-custom-cover",
|
||||
"version": "0.0.1",
|
||||
"description": "Cover card from home assistant",
|
||||
"main": "src/state-card-custom-cover.ts",
|
||||
"scripts": {
|
||||
"build": "webpack",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"private": true,
|
||||
"author": "Martin Bauer",
|
||||
"license": "GPLv3",
|
||||
"devDependencies": {
|
||||
"home-assistant-js-websocket": "^4.2.2",
|
||||
"lit-element": "^2.1.0",
|
||||
"ts-loader": "^6.0.2",
|
||||
"typescript": "^3.5.1",
|
||||
"webpack": "^4.33.0",
|
||||
"webpack-cli": "^3.3.4"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import {Connection, HassConfig, HassEntities, HassServices, MessageBase} from "home-assistant-js-websocket";
|
||||
|
||||
export interface HomeAssistant {
|
||||
connection: Connection;
|
||||
connected: boolean;
|
||||
states: HassEntities;
|
||||
services: HassServices;
|
||||
config: HassConfig;
|
||||
|
||||
callService: (
|
||||
domain: string,
|
||||
service: string,
|
||||
serviceData?: { [key: string]: any }
|
||||
) => Promise<void>;
|
||||
callApi: <T>(
|
||||
method: "GET" | "POST" | "PUT" | "DELETE",
|
||||
path: string,
|
||||
parameters?: { [key: string]: any }
|
||||
) => Promise<T>;
|
||||
fetchWithAuth: (
|
||||
path: string,
|
||||
init?: { [key: string]: any }
|
||||
) => Promise<Response>;
|
||||
sendWS: (msg: MessageBase) => void;
|
||||
callWS: <T>(msg: MessageBase) => Promise<T>;
|
||||
}
|
||||
208
custom_frontend_sources/room-glance-card/src/room-glance-card.ts
Normal file
@@ -0,0 +1,208 @@
|
||||
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;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
20
custom_frontend_sources/room-glance-card/tsconfig.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2017",
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"lib": [
|
||||
"es2017",
|
||||
"dom",
|
||||
"dom.iterable"
|
||||
],
|
||||
"noUnusedParameters": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"strict": true,
|
||||
"noImplicitAny": false,
|
||||
"skipLibCheck": true,
|
||||
"resolveJsonModule": true,
|
||||
"experimentalDecorators": true
|
||||
}
|
||||
}
|
||||
19
custom_frontend_sources/room-glance-card/webpack.config.js
Normal file
@@ -0,0 +1,19 @@
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
entry: "./src/room-glance-card.ts",
|
||||
output: {
|
||||
filename: 'room-glance-card.js',
|
||||
path: path.resolve(__dirname, 'dist')
|
||||
},
|
||||
resolve: {
|
||||
extensions: [".tsx", ".ts", ".js", ".json"]
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
// all files with a '.ts' or '.tsx' extension will be handled by 'ts-loader'
|
||||
{test: /\.tsx?$/, use: ["ts-loader"], exclude: /node_modules/}
|
||||
]
|
||||
},
|
||||
mode: "production"
|
||||
}
|
||||
207
custom_frontend_sources/state-card-custom-cover/dist/state-card-custom-cover.js
vendored
Normal file
4607
custom_frontend_sources/state-card-custom-cover/package-lock.json
generated
Normal file
21
custom_frontend_sources/state-card-custom-cover/package.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "state-card-custom-cover",
|
||||
"version": "0.0.1",
|
||||
"description": "Cover card from home assistant",
|
||||
"main": "src/state-card-custom-cover.ts",
|
||||
"scripts": {
|
||||
"build": "webpack",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"private": true,
|
||||
"author": "Martin Bauer",
|
||||
"license": "GPLv3",
|
||||
"devDependencies": {
|
||||
"home-assistant-js-websocket": "^4.2.2",
|
||||
"lit-element": "^2.1.0",
|
||||
"ts-loader": "^6.0.2",
|
||||
"typescript": "^3.5.1",
|
||||
"webpack": "^4.33.0",
|
||||
"webpack-cli": "^3.3.4"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
import {
|
||||
HassEntity,
|
||||
} from "home-assistant-js-websocket";
|
||||
import {HomeAssistant} from "./home-assistant-interface";
|
||||
|
||||
|
||||
const supportsFeature = (
|
||||
stateObj: HassEntity,
|
||||
feature: number
|
||||
): boolean => {
|
||||
// tslint:disable-next-line:no-bitwise
|
||||
return (stateObj.attributes.supported_features! & feature) !== 0;
|
||||
};
|
||||
|
||||
|
||||
/* eslint-enable no-bitwise */
|
||||
export class CoverEntity {
|
||||
|
||||
public hass: HomeAssistant;
|
||||
public stateObj: HassEntity;
|
||||
private _attr: { [key: string]: any; };
|
||||
private _feat: any;
|
||||
|
||||
constructor(hass : HomeAssistant, stateObj) {
|
||||
this.hass = hass;
|
||||
this.stateObj = stateObj;
|
||||
this._attr = stateObj.attributes;
|
||||
this._feat = this._attr.supported_features;
|
||||
}
|
||||
|
||||
get isFullyOpen() {
|
||||
if (this._attr.current_position !== undefined) {
|
||||
return this._attr.current_position === 100;
|
||||
}
|
||||
return this.stateObj.state === "open";
|
||||
}
|
||||
|
||||
get isFullyClosed() {
|
||||
if (this._attr.current_position !== undefined) {
|
||||
return this._attr.current_position === 0;
|
||||
}
|
||||
return this.stateObj.state === "closed";
|
||||
}
|
||||
|
||||
get isFullyOpenTilt() {
|
||||
return this._attr.current_tilt_position === 100;
|
||||
}
|
||||
|
||||
get isFullyClosedTilt() {
|
||||
return this._attr.current_tilt_position === 0;
|
||||
}
|
||||
|
||||
get isOpening() {
|
||||
return this.stateObj.state === "opening";
|
||||
}
|
||||
|
||||
get isClosing() {
|
||||
return this.stateObj.state === "closing";
|
||||
}
|
||||
|
||||
get supportsOpen() {
|
||||
return supportsFeature(this.stateObj, 1);
|
||||
}
|
||||
|
||||
get supportsClose() {
|
||||
return supportsFeature(this.stateObj, 2);
|
||||
}
|
||||
|
||||
get supportsSetPosition() {
|
||||
return supportsFeature(this.stateObj, 4);
|
||||
}
|
||||
|
||||
get supportsStop() {
|
||||
return supportsFeature(this.stateObj, 8);
|
||||
}
|
||||
|
||||
get supportsOpenTilt() {
|
||||
return supportsFeature(this.stateObj, 16);
|
||||
}
|
||||
|
||||
get supportsCloseTilt() {
|
||||
return supportsFeature(this.stateObj, 32);
|
||||
}
|
||||
|
||||
get supportsStopTilt() {
|
||||
return supportsFeature(this.stateObj, 64);
|
||||
}
|
||||
|
||||
get supportsSetTiltPosition() {
|
||||
return supportsFeature(this.stateObj, 128);
|
||||
}
|
||||
|
||||
get isTiltOnly() {
|
||||
const supportsCover =
|
||||
this.supportsOpen || this.supportsClose || this.supportsStop;
|
||||
const supportsTilt =
|
||||
this.supportsOpenTilt || this.supportsCloseTilt || this.supportsStopTilt;
|
||||
return supportsTilt && !supportsCover;
|
||||
}
|
||||
|
||||
openCover() {
|
||||
this.callService("open_cover");
|
||||
}
|
||||
|
||||
closeCover() {
|
||||
this.callService("close_cover");
|
||||
}
|
||||
|
||||
stopCover() {
|
||||
this.callService("stop_cover");
|
||||
}
|
||||
|
||||
openCoverTilt() {
|
||||
this.callService("open_cover_tilt");
|
||||
}
|
||||
|
||||
closeCoverTilt() {
|
||||
this.callService("close_cover_tilt");
|
||||
}
|
||||
|
||||
stopCoverTilt() {
|
||||
this.callService("stop_cover_tilt");
|
||||
}
|
||||
|
||||
setCoverPosition(position) {
|
||||
this.callService("set_cover_position", { position });
|
||||
}
|
||||
|
||||
setCoverTiltPosition(tiltPosition) {
|
||||
this.callService("set_cover_tilt_position", {
|
||||
tilt_position: tiltPosition,
|
||||
});
|
||||
}
|
||||
|
||||
// helper method
|
||||
|
||||
callService(service, data = {}) {
|
||||
data['entity_id'] = this.stateObj.entity_id;
|
||||
this.hass.callService("cover", service, data);
|
||||
}
|
||||
}
|
||||
|
||||
export const supportsOpen = (stateObj) => supportsFeature(stateObj, 1);
|
||||
|
||||
export const supportsClose = (stateObj) => supportsFeature(stateObj, 2);
|
||||
|
||||
export const supportsSetPosition = (stateObj) => supportsFeature(stateObj, 4);
|
||||
|
||||
export const supportsStop = (stateObj) => supportsFeature(stateObj, 8);
|
||||
|
||||
export const supportsOpenTilt = (stateObj) => supportsFeature(stateObj, 16);
|
||||
|
||||
export const supportsCloseTilt = (stateObj) => supportsFeature(stateObj, 32);
|
||||
|
||||
export const supportsStopTilt = (stateObj) => supportsFeature(stateObj, 64);
|
||||
|
||||
export const supportsSetTiltPosition = (stateObj) =>
|
||||
supportsFeature(stateObj, 128);
|
||||
|
||||
export function isTiltOnly(stateObj) {
|
||||
const supportsCover =
|
||||
supportsOpen(stateObj) || supportsClose(stateObj) || supportsStop(stateObj);
|
||||
const supportsTilt =
|
||||
supportsOpenTilt(stateObj) ||
|
||||
supportsCloseTilt(stateObj) ||
|
||||
supportsStopTilt(stateObj);
|
||||
return supportsTilt && !supportsCover;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import {Connection, HassConfig, HassEntities, HassServices, MessageBase} from "home-assistant-js-websocket";
|
||||
|
||||
export interface HomeAssistant {
|
||||
connection: Connection;
|
||||
connected: boolean;
|
||||
states: HassEntities;
|
||||
services: HassServices;
|
||||
config: HassConfig;
|
||||
|
||||
callService: (
|
||||
domain: string,
|
||||
service: string,
|
||||
serviceData?: { [key: string]: any }
|
||||
) => Promise<void>;
|
||||
callApi: <T>(
|
||||
method: "GET" | "POST" | "PUT" | "DELETE",
|
||||
path: string,
|
||||
parameters?: { [key: string]: any }
|
||||
) => Promise<T>;
|
||||
fetchWithAuth: (
|
||||
path: string,
|
||||
init?: { [key: string]: any }
|
||||
) => Promise<Response>;
|
||||
sendWS: (msg: MessageBase) => void;
|
||||
callWS: <T>(msg: MessageBase) => Promise<T>;
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
import {LitElement, html, customElement, property, TemplateResult} from "lit-element";
|
||||
import {CoverEntity} from "./cover-model"
|
||||
import {HomeAssistant} from "./home-assistant-interface";
|
||||
|
||||
|
||||
export interface CustomCoverStateCardConfig {
|
||||
type: string;
|
||||
entity: string;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
@customElement("state-card-custom-cover")
|
||||
export class StateCardCustomCover extends LitElement {
|
||||
@property() public hass?: HomeAssistant;
|
||||
|
||||
@property() private _config?: CustomCoverStateCardConfig;
|
||||
|
||||
@property()
|
||||
public get stateObj() {
|
||||
if (this.hass && this._config)
|
||||
return this.hass.states[this._config.entity];
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
@property() public inDialog: boolean = false;
|
||||
|
||||
|
||||
public setConfig(config: CustomCoverStateCardConfig | undefined) {
|
||||
if (!config || !config.entity) {
|
||||
throw new Error("Invalid configuration");
|
||||
}
|
||||
this._config = config;
|
||||
}
|
||||
|
||||
|
||||
get entityObj(): CoverEntity {
|
||||
if (this.hass && this.stateObj)
|
||||
return new CoverEntity(this.hass, this.stateObj);
|
||||
else
|
||||
throw new Error("Trying to get entityObj before setting hass & config");
|
||||
}
|
||||
|
||||
public static getCardSize(): number {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
protected stateInfoTemplate() {
|
||||
return html`
|
||||
State info template
|
||||
`;
|
||||
}
|
||||
|
||||
protected render(): TemplateResult | void {
|
||||
if (!this._config || !this.hass) {
|
||||
return html``;
|
||||
}
|
||||
|
||||
const entityObj = this.entityObj;
|
||||
const stateObj = this.hass.states[this._config.entity];
|
||||
|
||||
if (!stateObj) {
|
||||
return html`
|
||||
<hui-warning
|
||||
>Does not work :(</hui-warning
|
||||
>
|
||||
`;
|
||||
}
|
||||
|
||||
return html`
|
||||
<style include="iron-flex iron-flex-alignment"></style>
|
||||
<style>
|
||||
:host {
|
||||
line-height: 1.5;
|
||||
}
|
||||
.state {
|
||||
white-space: nowrap;
|
||||
}
|
||||
[invisible] {
|
||||
visibility: hidden !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<hui-generic-entity-row .config="${this._config}" .hass="${this.hass}">
|
||||
<div class="state">
|
||||
<paper-icon-button
|
||||
icon="hass:menu"
|
||||
@click=${this.onHalfOpenTap}
|
||||
></paper-icon-button>
|
||||
<paper-icon-button
|
||||
icon="hass:arrow-up"
|
||||
@click=${this.onOpenTap}
|
||||
.disabled="${this.computeOpenDisabled(stateObj, this.entityObj)}"
|
||||
></paper-icon-button>
|
||||
<paper-icon-button
|
||||
icon="hass:stop"
|
||||
@click=${this.onStopTap}
|
||||
></paper-icon-button>
|
||||
<paper-icon-button
|
||||
icon="hass:arrow-down"
|
||||
@click=${this.onCloseTap}
|
||||
.disabled="${this.computeClosedDisabled(stateObj, entityObj)}"
|
||||
></paper-icon-button>
|
||||
</div>
|
||||
</hui-generic-entity-row>
|
||||
`;
|
||||
}
|
||||
|
||||
computeOpenDisabled(stateObj, entityObj) {
|
||||
const assumedState = stateObj.attributes.assumed_state === true;
|
||||
return (entityObj.isFullyOpen || entityObj.isOpening) && !assumedState;
|
||||
}
|
||||
|
||||
computeClosedDisabled(stateObj, entityObj) {
|
||||
const assumedState = stateObj.attributes.assumed_state === true;
|
||||
return (entityObj.isFullyClosed || entityObj.isClosing) && !assumedState;
|
||||
}
|
||||
|
||||
private onHalfOpenTap(ev) {
|
||||
const stateObj = this.hass!.states[this._config!.entity];
|
||||
ev.stopPropagation();
|
||||
this.entityObj.setCoverPosition(stateObj.attributes['half_position']);
|
||||
}
|
||||
|
||||
private onOpenTap(ev) {
|
||||
ev.stopPropagation();
|
||||
this.entityObj.openCover();
|
||||
}
|
||||
|
||||
private onCloseTap(ev) {
|
||||
ev.stopPropagation();
|
||||
this.entityObj.closeCover();
|
||||
}
|
||||
|
||||
private onStopTap(ev) {
|
||||
ev.stopPropagation();
|
||||
this.entityObj.stopCover();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2017",
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"lib": [
|
||||
"es2017",
|
||||
"dom",
|
||||
"dom.iterable"
|
||||
],
|
||||
"noUnusedParameters": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"strict": true,
|
||||
"noImplicitAny": false,
|
||||
"skipLibCheck": true,
|
||||
"resolveJsonModule": true,
|
||||
"experimentalDecorators": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
entry: "./src/state-card-custom-cover.ts",
|
||||
output: {
|
||||
filename: 'state-card-custom-cover.js',
|
||||
path: path.resolve(__dirname, 'dist')
|
||||
},
|
||||
resolve: {
|
||||
extensions: [".tsx", ".ts", ".js", ".json"]
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
// all files with a '.ts' or '.tsx' extension will be handled by 'ts-loader'
|
||||
{test: /\.tsx?$/, use: ["ts-loader"], exclude: /node_modules/}
|
||||
]
|
||||
},
|
||||
mode: "production"
|
||||
}
|
||||