From 48f6d1dfec837f5206907d6b53775f5c37f6065c Mon Sep 17 00:00:00 2001 From: Zack Arnett Date: Mon, 15 Oct 2018 13:14:43 -0400 Subject: [PATCH] Adding Alarm Panel to Lovelace (#1758) * Adding Alarm Panel * Updating error in Lint * Review Changes * Using label-badge for upper right icon * Resolving Reviews * Prettier Fixes * Updating style to fix overlapping state badge * Adding Alarm Card back to create element * Resolving reviews and reposition of Icon * Updating to Localize Labels --- .../src/demos/demo-hui-alarm-panel-card.js | 75 +++++ .../lovelace/cards/hui-alarm-panel-card.js | 258 ++++++++++++++++++ .../lovelace/common/create-card-element.js | 2 + 3 files changed, 335 insertions(+) create mode 100644 gallery/src/demos/demo-hui-alarm-panel-card.js create mode 100644 src/panels/lovelace/cards/hui-alarm-panel-card.js diff --git a/gallery/src/demos/demo-hui-alarm-panel-card.js b/gallery/src/demos/demo-hui-alarm-panel-card.js new file mode 100644 index 0000000000..23c95804b5 --- /dev/null +++ b/gallery/src/demos/demo-hui-alarm-panel-card.js @@ -0,0 +1,75 @@ +import { html } from "@polymer/polymer/lib/utils/html-tag.js"; +import { PolymerElement } from "@polymer/polymer/polymer-element.js"; + +import getEntity from "../data/entity.js"; +import provideHass from "../data/provide_hass.js"; +import "../components/demo-cards.js"; + +const ENTITIES = [ + getEntity("alarm_control_panel", "alarm", "disarmed", { + friendly_name: "Alarm", + }), + getEntity("alarm_control_panel", "alarm_armed", "armed_home", { + friendly_name: "Alarm", + }), +]; + +const CONFIGS = [ + { + heading: "Basic Example", + config: ` +- type: alarm-panel + entity: alarm_control_panel.alarm + `, + }, + { + heading: "With Title", + config: ` +- type: alarm-panel + entity: alarm_control_panel.alarm_armed + title: My Alarm + `, + }, + { + heading: "Using only Arm_Home State", + config: ` +- type: alarm-panel + entity: alarm_control_panel.alarm + states: + - arm_home + `, + }, + { + heading: "Invalid Entity", + config: ` +- type: alarm-panel + entity: alarm_control_panel.alarm1 + `, + }, +]; + +class DemoAlarmPanelEntity extends PolymerElement { + static get template() { + return html` + + `; + } + + static get properties() { + return { + _configs: { + type: Object, + value: CONFIGS, + }, + hass: Object, + }; + } + + ready() { + super.ready(); + const hass = provideHass(this.$.demos); + hass.addEntities(ENTITIES); + } +} + +customElements.define("demo-hui-alarm-panel-card", DemoAlarmPanelEntity); diff --git a/src/panels/lovelace/cards/hui-alarm-panel-card.js b/src/panels/lovelace/cards/hui-alarm-panel-card.js new file mode 100644 index 0000000000..f14ac4b801 --- /dev/null +++ b/src/panels/lovelace/cards/hui-alarm-panel-card.js @@ -0,0 +1,258 @@ +import { html } from "@polymer/polymer/lib/utils/html-tag.js"; +import { PolymerElement } from "@polymer/polymer/polymer-element.js"; + +import "../../../components/ha-card.js"; + +import EventsMixin from "../../../mixins/events-mixin.js"; +import LocalizeMixin from "../../../mixins/localize-mixin.js"; +import "../../../components/ha-label-badge.js"; + +/* + * @appliesMixin EventsMixin + */ + +const Icons = { + armed_away: "hass:security-lock", + armed_custom_bypass: "hass:security", + armed_home: "hass:security-home", + armed_night: "hass:security-home", + disarmed: "hass:verified", + pending: "hass:shield-outline", + triggered: "hass:bell-ring", +}; + +class HuiAlarmPanelCard extends LocalizeMixin(EventsMixin(PolymerElement)) { + static get template() { + return html` + + + + + + `; + } + + static get properties() { + return { + hass: { + type: Object, + }, + _config: Object, + _stateObj: { + type: Object, + computed: "_computeStateObj(hass.states, _config.entity)", + }, + _value: { + type: String, + value: "", + }, + }; + } + + getCardSize() { + return 4; + } + + setConfig(config) { + if ( + !config || + !config.entity || + config.entity.split(".")[0] !== "alarm_control_panel" + ) { + throw new Error("Invalid card configuration"); + } + + const defaults = { + states: ["arm_away", "arm_home"], + }; + + this._config = { ...defaults, ...config }; + this._icons = Icons; + } + + _computeStateObj(states, entityId) { + return states && entityId in states ? states[entityId] : null; + } + + _computeHeader(localize, stateObj) { + if (!stateObj) return ""; + return this._config.title + ? this._config.title + : this._label(localize, stateObj.state); + } + + _computeIcon(stateObj) { + return this._icons[stateObj.state] || "hass:shield-outline"; + } + + _label(localize, state) { + return ( + localize(`state.alarm_control_panel.${state}`) || + localize(`ui.card.alarm_control_panel.${state}`) + ); + } + + _stateIconLabel(state) { + const stateLabel = state.split("_").pop(); + return stateLabel === "disarmed" || stateLabel === "triggered" + ? "" + : stateLabel; + } + + _showActionToggle(state) { + return state === "disarmed"; + } + + _computeClassName(stateObj) { + if (!stateObj) return "not-found"; + return ""; + } + + _handlePadClick(e) { + const val = e.target.getAttribute("value"); + this._value = val === "clear" ? "" : this._value + val; + } + + _handleActionClick(e) { + this.hass.callService("alarm_control_panel", "alarm_" + e.target.id, { + entity_id: this._stateObj.entity_id, + code: this._value, + }); + this._value = ""; + } +} + +customElements.define("hui-alarm-panel-card", HuiAlarmPanelCard); diff --git a/src/panels/lovelace/common/create-card-element.js b/src/panels/lovelace/common/create-card-element.js index ea76238289..7422f9187b 100644 --- a/src/panels/lovelace/common/create-card-element.js +++ b/src/panels/lovelace/common/create-card-element.js @@ -1,5 +1,6 @@ import { fireEvent } from "../../../common/dom/fire_event.js"; +import "../cards/hui-alarm-panel-card.js"; import "../cards/hui-conditional-card.js"; import "../cards/hui-entities-card.js"; import "../cards/hui-entity-filter-card.js"; @@ -24,6 +25,7 @@ import "../cards/hui-gauge-card.js"; import createErrorCardConfig from "./create-error-card-config.js"; const CARD_TYPES = new Set([ + "alarm-panel", "conditional", "entities", "entity-filter",