home-assistant-frontend/src/panels/config/integrations/integration-panels/zwave/zwave-groups.js

381 lines
11 KiB
JavaScript

import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
import "@polymer/paper-item/paper-item";
import "@polymer/paper-listbox/paper-listbox";
import { html } from "@polymer/polymer/lib/utils/html-tag";
/* eslint-plugin-disable lit */
import { PolymerElement } from "@polymer/polymer/polymer-element";
import { computeStateName } from "../../../../../common/entity/compute_state_name";
import "../../../../../components/buttons/ha-call-service-button";
import "../../../../../components/ha-card";
import LocalizeMixin from "../../../../../mixins/localize-mixin";
import "../../../../../styles/polymer-ha-style";
class ZwaveGroups extends LocalizeMixin(PolymerElement) {
static get template() {
return html`
<style include="iron-flex ha-style">
.content {
margin-top: 24px;
}
ha-card {
margin: 0 auto;
max-width: 600px;
}
.device-picker {
@apply --layout-horizontal;
@apply --layout-center-center;
padding-left: 24px;
padding-right: 24px;
padding-bottom: 24px;
}
.help-text {
padding-left: 24px;
padding-right: 24px;
padding-bottom: 12px;
}
</style>
<ha-card
class="content"
header="[[localize('ui.panel.config.zwave.node_management.node_group_associations')]]"
>
<!-- TODO make api for getting groups and members -->
<div class="device-picker">
<paper-dropdown-menu
label="[[localize('ui.panel.config.zwave.node_management.group')]]"
dynamic-align=""
class="flex"
>
<paper-listbox
slot="dropdown-content"
selected="{{_selectedGroup}}"
>
<template is="dom-repeat" items="[[groups]]" as="state">
<paper-item>[[_computeSelectCaptionGroup(state)]]</paper-item>
</template>
</paper-listbox>
</paper-dropdown-menu>
</div>
<template is="dom-if" if="[[_computeIsGroupSelected(_selectedGroup)]]">
<div class="device-picker">
<paper-dropdown-menu
label="[[localize('ui.panel.config.zwave.node_management.node_to_control')]]"
dynamic-align=""
class="flex"
>
<paper-listbox
slot="dropdown-content"
selected="{{_selectedTargetNode}}"
>
<template is="dom-repeat" items="[[nodes]]" as="state">
<paper-item>[[_computeSelectCaption(state)]]</paper-item>
</template>
</paper-listbox>
</paper-dropdown-menu>
</div>
<div class="help-text">
<span
>[[localize('ui.panel.config.zwave.node_management.nodes_in_group')]]</span
>
<template is="dom-repeat" items="[[_otherGroupNodes]]" as="state">
<div>[[state]]</div>
</template>
</div>
<div class="help-text">
<span
>[[localize('ui.panel.config.zwave.node_management.max_associations')]]</span
>
<span>[[_maxAssociations]]</span>
</div>
</template>
<template
is="dom-if"
if="[[_computeIsTargetNodeSelected(_selectedTargetNode)]]"
>
<div class="card-actions">
<template is="dom-if" if="[[!_noAssociationsLeft]]">
<ha-call-service-button
hass="[[hass]]"
domain="zwave"
service="change_association"
service-data="[[_addAssocServiceData]]"
>
[[localize('ui.panel.config.zwave.node_management.add_to_group')]]
</ha-call-service-button>
</template>
<template
is="dom-if"
if="[[_computeTargetInGroup(_selectedGroup, _selectedTargetNode)]]"
>
<ha-call-service-button
hass="[[hass]]"
domain="zwave"
service="change_association"
service-data="[[_removeAssocServiceData]]"
>
[[localize('ui.panel.config.zwave.node_management.remove_from_group')]]
</ha-call-service-button>
</template>
<template is="dom-if" if="[[_isBroadcastNodeInGroup]]">
<ha-call-service-button
hass="[[hass]]"
domain="zwave"
service="change_association"
service-data="[[_removeBroadcastNodeServiceData]]"
>
[[localize('ui.panel.config.zwave.node_management.remove_broadcast')]]
</ha-call-service-button>
</template>
</div>
</template>
</ha-card>
`;
}
static get properties() {
return {
hass: Object,
nodes: Array,
groups: Array,
selectedNode: {
type: Number,
observer: "_selectedNodeChanged",
},
_selectedTargetNode: {
type: Number,
value: -1,
observer: "_selectedTargetNodeChanged",
},
_selectedGroup: {
type: Number,
value: -1,
},
_otherGroupNodes: {
type: Array,
value: -1,
computed: "_computeOtherGroupNodes(_selectedGroup)",
},
_maxAssociations: {
type: String,
value: "",
computed: "_computeMaxAssociations(_selectedGroup)",
},
_noAssociationsLeft: {
type: Boolean,
value: true,
computed: "_computeAssociationsLeft(_selectedGroup)",
},
_addAssocServiceData: {
type: String,
value: "",
},
_removeAssocServiceData: {
type: String,
value: "",
},
_removeBroadcastNodeServiceData: {
type: String,
value: "",
},
_isBroadcastNodeInGroup: {
type: Boolean,
value: false,
},
};
}
static get observers() {
return ["_selectedGroupChanged(groups, _selectedGroup)"];
}
ready() {
super.ready();
this.addEventListener("hass-service-called", (ev) =>
this.serviceCalled(ev)
);
}
serviceCalled(ev) {
if (ev.detail.success) {
setTimeout(() => {
this._refreshGroups(this.selectedNode);
}, 5000);
}
}
_computeAssociationsLeft(selectedGroup) {
if (selectedGroup === -1) return true;
return this._maxAssociations === this._otherGroupNodes.length;
}
_computeMaxAssociations(selectedGroup) {
if (selectedGroup === -1) return -1;
const maxAssociations = this.groups[selectedGroup].value.max_associations;
if (!maxAssociations) return "None";
return maxAssociations;
}
_computeOtherGroupNodes(selectedGroup) {
if (selectedGroup === -1) return -1;
this.setProperties({ _isBroadcastNodeInGroup: false });
const associations = Object.values(
this.groups[selectedGroup].value.association_instances
);
if (!associations.length) return ["None"];
return associations.map((assoc) => {
if (!assoc.length || assoc.length !== 2) {
return `Unknown Node: ${assoc}`;
}
const id = assoc[0];
const instance = assoc[1];
const node = this.nodes.find((n) => n.attributes.node_id === id);
if (id === 255) {
this.setProperties({
_isBroadcastNodeInGroup: true,
_removeBroadcastNodeServiceData: {
node_id: this.nodes[this.selectedNode].attributes.node_id,
association: "remove",
target_node_id: 255,
group: this.groups[selectedGroup].key,
},
});
}
if (!node) {
return `Unknown Node (${id}: (${instance} ? ${id}.${instance} : ${id}))`;
}
let caption = this._computeSelectCaption(node);
if (instance) {
caption += `/ Instance: ${instance}`;
}
return caption;
});
}
_computeTargetInGroup(selectedGroup, selectedTargetNode) {
if (selectedGroup === -1 || selectedTargetNode === -1) return false;
const associations = Object.values(
this.groups[selectedGroup].value.associations
);
if (!associations.length) return false;
return (
associations.indexOf(
this.nodes[selectedTargetNode].attributes.node_id
) !== -1
);
}
_computeSelectCaption(stateObj) {
return `${computeStateName(stateObj)}
(Node: ${stateObj.attributes.node_id}
${stateObj.attributes.query_stage})`;
}
_computeSelectCaptionGroup(stateObj) {
return `${stateObj.key}: ${stateObj.value.label}`;
}
_computeIsTargetNodeSelected(selectedTargetNode) {
return this.nodes && selectedTargetNode !== -1;
}
_computeIsGroupSelected(selectedGroup) {
return this.nodes && this.selectedNode !== -1 && selectedGroup !== -1;
}
_computeAssocServiceData(selectedGroup, type) {
if (
!this.groups ||
selectedGroup === -1 ||
this.selectedNode === -1 ||
this._selectedTargetNode === -1
) {
return -1;
}
return {
node_id: this.nodes[this.selectedNode].attributes.node_id,
association: type,
target_node_id: this.nodes[this._selectedTargetNode].attributes.node_id,
group: this.groups[selectedGroup].key,
};
}
async _refreshGroups(selectedNode) {
const groupData = [];
const groups = await this.hass.callApi(
"GET",
`zwave/groups/${this.nodes[selectedNode].attributes.node_id}`
);
Object.keys(groups).forEach((key) => {
groupData.push({
key,
value: groups[key],
});
});
this.setProperties({
groups: groupData,
_maxAssociations: groupData[this._selectedGroup].value.max_associations,
_otherGroupNodes: Object.values(
groupData[this._selectedGroup].value.associations
),
_isBroadcastNodeInGroup: false,
});
const oldGroup = this._selectedGroup;
this.setProperties({ _selectedGroup: -1 });
this.setProperties({ _selectedGroup: oldGroup });
}
_selectedGroupChanged() {
if (this._selectedGroup === -1) return;
this.setProperties({
_maxAssociations: this.groups[this._selectedGroup].value.max_associations,
_otherGroupNodes: Object.values(
this.groups[this._selectedGroup].value.associations
),
});
}
_selectedTargetNodeChanged() {
if (this._selectedGroup === -1) return;
if (
this._computeTargetInGroup(this._selectedGroup, this._selectedTargetNode)
) {
this.setProperties({
_removeAssocServiceData: this._computeAssocServiceData(
this._selectedGroup,
"remove"
),
});
} else {
this.setProperties({
_addAssocServiceData: this._computeAssocServiceData(
this._selectedGroup,
"add"
),
});
}
}
_selectedNodeChanged() {
if (this.selectedNode === -1) return;
this.setProperties({ _selectedTargetNode: -1, _selectedGroup: -1 });
}
}
customElements.define("zwave-groups", ZwaveGroups);