mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-18 23:06:40 +00:00
Add initial group config panel (#218)
* Add initial group config * Tweak labels for group form
This commit is contained in:
parent
d5ca790686
commit
5d223c8da4
@ -21,7 +21,8 @@
|
|||||||
"polymer": "Polymer/polymer#~1.8.0",
|
"polymer": "Polymer/polymer#~1.8.0",
|
||||||
"vaadin-combo-box": "vaadin/vaadin-combo-box#~1.1.5",
|
"vaadin-combo-box": "vaadin/vaadin-combo-box#~1.1.5",
|
||||||
"paper-slider": "1.0.13",
|
"paper-slider": "1.0.13",
|
||||||
"leaflet": "^1.0.2"
|
"leaflet": "^1.0.2",
|
||||||
|
"polymer-sortablejs": "^0.1.3"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"paper-slider": "1.0.13"
|
"paper-slider": "1.0.13"
|
||||||
|
85
panels/config/group/ha-config-section-group.html
Normal file
85
panels/config/group/ha-config-section-group.html
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
<link rel="import" href="../../../bower_components/polymer/polymer.html">
|
||||||
|
<link rel="import" href="../../../bower_components/paper-button/paper-button.html">
|
||||||
|
<link rel="import" href="../../../bower_components/paper-card/paper-card.html">
|
||||||
|
<link rel="import" href="../../../bower_components/paper-checkbox/paper-checkbox.html">
|
||||||
|
<link rel="import" href="../../../bower_components/paper-spinner/paper-spinner.html">
|
||||||
|
<link rel="import" href="../../../bower_components/paper-dropdown-menu/paper-dropdown-menu.html">
|
||||||
|
<link rel='import' href='../../../bower_components/paper-listbox/paper-listbox.html'>
|
||||||
|
<link rel='import' href='../../../bower_components/paper-item/paper-item.html'>
|
||||||
|
|
||||||
|
<link rel="import" href="../../../src/resources/ha-style.html">
|
||||||
|
|
||||||
|
<link rel="import" href="../ha-config-section.html">
|
||||||
|
<link rel="import" href="../ha-entity-config.html">
|
||||||
|
<link rel="import" href="./ha-form-group.html">
|
||||||
|
|
||||||
|
<dom-module id="ha-config-section-group">
|
||||||
|
<template>
|
||||||
|
<ha-config-section is-wide='[[isWide]]'>
|
||||||
|
<span slot='header'>Groups & Views</span>
|
||||||
|
<span slot='introduction'>
|
||||||
|
Use groups to organize your entities and make Home Assistant really your own.
|
||||||
|
<br><br>
|
||||||
|
Got more groups than you can handle? Create views to manage your groups.
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<ha-entity-config
|
||||||
|
hass='[[hass]]'
|
||||||
|
label='Group'
|
||||||
|
entities='[[entities]]'
|
||||||
|
config='[[entityConfig]]'>
|
||||||
|
</ha-entity-config>
|
||||||
|
</ha-config-section>
|
||||||
|
</template>
|
||||||
|
</dom-module>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
Polymer({
|
||||||
|
is: 'ha-config-section-group',
|
||||||
|
|
||||||
|
properties: {
|
||||||
|
hass: {
|
||||||
|
type: Object,
|
||||||
|
},
|
||||||
|
|
||||||
|
isWide: {
|
||||||
|
type: Boolean,
|
||||||
|
value: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
entities: {
|
||||||
|
type: Array,
|
||||||
|
computed: 'computeEntities(hass)',
|
||||||
|
},
|
||||||
|
|
||||||
|
entityConfig: {
|
||||||
|
type: Object,
|
||||||
|
value: {
|
||||||
|
component: 'ha-form-group',
|
||||||
|
computeSelectCaption: function (stateObj) {
|
||||||
|
return window.hassUtil.computeStateName(stateObj) +
|
||||||
|
(stateObj.attributes.view ? ' (view)' : '');
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computeEntities: function (hass) {
|
||||||
|
return Object.keys(hass.states)
|
||||||
|
.map(function (key) { return hass.states[key]; })
|
||||||
|
.filter(function (entity) {
|
||||||
|
return (window.hassUtil.computeDomain(entity) === 'group' &&
|
||||||
|
!entity.attributes.auto);
|
||||||
|
})
|
||||||
|
.sort(function (entityA, entityB) {
|
||||||
|
if (entityA.entity_id < entityB.entity_id) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (entityA.entity_id > entityB.entity_id) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
196
panels/config/group/ha-form-group.html
Normal file
196
panels/config/group/ha-form-group.html
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
<link rel="import" href="../../../bower_components/polymer/polymer.html">
|
||||||
|
<link rel="import" href="../../../bower_components/iron-icon/iron-icon.html">
|
||||||
|
<link rel="import" href="../../../bower_components/paper-icon-button/paper-icon-button.html">
|
||||||
|
<link rel="import" href="../../../bower_components/paper-menu-button/paper-menu-button.html">
|
||||||
|
<link rel="import" href="../../../bower_components/paper-radio-group/paper-radio-group.html">
|
||||||
|
<link rel="import" href="../../../bower_components/paper-radio-button/paper-radio-button.html">
|
||||||
|
<link rel="import" href="../../../bower_components/paper-menu/paper-menu.html">
|
||||||
|
<link rel="import" href="../../../bower_components/polymer-sortablejs/polymer-sortablejs.html">
|
||||||
|
|
||||||
|
<link rel="import" href="../../../src/components/entity/state-info.html">
|
||||||
|
|
||||||
|
<link rel="import" href="../ha-form-style.html">
|
||||||
|
|
||||||
|
<dom-module id="ha-form-group">
|
||||||
|
<template>
|
||||||
|
<style include="iron-flex ha-style ha-form-style">
|
||||||
|
.entities-header {
|
||||||
|
@apply(--layout-horizontal);
|
||||||
|
@apply(--layout-justified);
|
||||||
|
@apply(--layout-center);
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drag-handle {
|
||||||
|
cursor: -webkit-grab;
|
||||||
|
cursor: -moz-grab;
|
||||||
|
cursor: grab;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sortable-chosen .drag-handle, .sortable-ghost {
|
||||||
|
cursor: -webkit-grabbing;
|
||||||
|
cursor: -moz-grabbing;
|
||||||
|
cursor: grabbing;
|
||||||
|
}
|
||||||
|
|
||||||
|
sortable-js {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.entity-row {
|
||||||
|
@apply(--layout-horizontal);
|
||||||
|
@apply(--layout-center);
|
||||||
|
padding: 4px 0;
|
||||||
|
border-top: 1px solid rgba(0, 0, 0, .12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.entity-row:first-child {
|
||||||
|
border-top: 1px solid rgba(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.entity-row.sortable-chosen {
|
||||||
|
background-color: var(--paper-grey-200);
|
||||||
|
/* invisible border so we don't change height. */
|
||||||
|
border-top: 1px solid rgba(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.entity-row .unknown {
|
||||||
|
padding-left: 56px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.entity-row paper-icon-button {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.entity-row:not(.sortable-chosen):hover paper-icon-button {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div class='form-group'>
|
||||||
|
<paper-input
|
||||||
|
class='form-control flex'
|
||||||
|
label='Name'
|
||||||
|
value='{{entityName}}'>
|
||||||
|
</paper-input>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='form-group'>
|
||||||
|
<label>Type</label>
|
||||||
|
<paper-radio-group
|
||||||
|
selected='{{entityType}}'
|
||||||
|
class='form-control'
|
||||||
|
>
|
||||||
|
<paper-radio-button name='group'>Group</paper-radio-button>
|
||||||
|
<paper-radio-button name='view'>View</paper-radio-button>
|
||||||
|
</paper-radio-group>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='form-group vertical entities'>
|
||||||
|
<div class='entities-header'>
|
||||||
|
<label>Entities (drag to reorder):</label>
|
||||||
|
<!-- To be done
|
||||||
|
<paper-menu-button
|
||||||
|
dynamic-align
|
||||||
|
class='form-control'
|
||||||
|
>
|
||||||
|
<paper-icon-button
|
||||||
|
icon='mdi:plus'
|
||||||
|
class="dropdown-trigger"
|
||||||
|
></paper-icon-button>
|
||||||
|
<paper-listbox
|
||||||
|
class="dropdown-content"
|
||||||
|
selected='{{entityPollingIntensity}}'
|
||||||
|
>
|
||||||
|
<paper-item>Do not poll (0)</paper-item>
|
||||||
|
<paper-item>Poll every time (1)</paper-item>
|
||||||
|
<paper-item>Poll every other time (2)</paper-item>
|
||||||
|
</paper-listbox>
|
||||||
|
</paper-menu-button>
|
||||||
|
-->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<sortable-js
|
||||||
|
class='form-control'
|
||||||
|
on-choose='handleRowChosen'
|
||||||
|
handle='.drag-handle'
|
||||||
|
>
|
||||||
|
<template is="dom-repeat" items='{{entityChildren}}'>
|
||||||
|
<div class='entity-row'>
|
||||||
|
<iron-icon icon='mdi:drag-vertical' class='drag-handle'></iron-icon>
|
||||||
|
<template is='dom-if' if='[[!item.state]]'>
|
||||||
|
<div class='unknown flex'>Unknown entity [[item.entity_id]]</div>
|
||||||
|
</template>
|
||||||
|
<template is='dom-if' if='[[item.state]]' restamp>
|
||||||
|
<state-info state-obj='[[item]]' class='flex'></state-info>
|
||||||
|
</template>
|
||||||
|
<!-- <paper-icon-button icon='mdi:delete'></paper-icon-button> -->
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</sortable-js>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</dom-module>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
Polymer({
|
||||||
|
is: 'ha-form-group',
|
||||||
|
|
||||||
|
properties: {
|
||||||
|
hass: {
|
||||||
|
type: Object,
|
||||||
|
},
|
||||||
|
|
||||||
|
entity: {
|
||||||
|
type: Object,
|
||||||
|
},
|
||||||
|
|
||||||
|
entityName: {
|
||||||
|
type: String,
|
||||||
|
value: '',
|
||||||
|
},
|
||||||
|
|
||||||
|
entityType: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
|
||||||
|
entityChildren: {
|
||||||
|
type: Object,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
handleRowChosen: function (ev) {
|
||||||
|
// Polymer element and sortablejs both fire the same events, filter one out
|
||||||
|
if (!ev.detail || !window.navigator.vibrate) return;
|
||||||
|
|
||||||
|
// Tell the user that moving his finger now will start dragging.
|
||||||
|
window.navigator.vibrate(50);
|
||||||
|
},
|
||||||
|
|
||||||
|
loadEntity: function (entity) {
|
||||||
|
var states = this.hass.states;
|
||||||
|
this.entity = entity;
|
||||||
|
this.entityName = entity.attributes.friendly_name || '';
|
||||||
|
this.entityType = entity.attributes.view ? 'view' : 'group';
|
||||||
|
this.entityChildren = entity.attributes.entity_id
|
||||||
|
.map(function (ent) {
|
||||||
|
return states[ent] || { state: false, entity_id: ent, attributes: {} };
|
||||||
|
});
|
||||||
|
return Promise.resolve();
|
||||||
|
},
|
||||||
|
|
||||||
|
saveEntity: function () {
|
||||||
|
var data = {
|
||||||
|
name: this.entityName,
|
||||||
|
view: this.entityType === 'view',
|
||||||
|
entities: this.entityChildren.map(function (ent) { return ent.entity_id; }),
|
||||||
|
};
|
||||||
|
|
||||||
|
var objectId = this.entity.entity_id.split('.')[1];
|
||||||
|
return this.hass.callApi('POST', 'config/group/config/' + objectId, data);
|
||||||
|
},
|
||||||
|
|
||||||
|
// deleteEntity: function () {
|
||||||
|
// return new Promise.resolve();
|
||||||
|
// }
|
||||||
|
});
|
||||||
|
</script>
|
@ -31,7 +31,7 @@
|
|||||||
margin-top: -24px;
|
margin-top: -24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel ::slotted(paper-card) {
|
.panel ::slotted(*) {
|
||||||
margin-top: 24px;
|
margin-top: 24px;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
.device-picker {
|
.device-picker {
|
||||||
@apply(--layout-horizontal);
|
@apply(--layout-horizontal);
|
||||||
padding-bottom: 32px;
|
padding-bottom: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-placeholder {
|
.form-placeholder {
|
||||||
@ -19,12 +19,17 @@
|
|||||||
[hidden]: {
|
[hidden]: {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card-actions {
|
||||||
|
@apply(--layout-horizontal);
|
||||||
|
@apply(--layout-justified);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<paper-card>
|
<paper-card>
|
||||||
<div class='card-content'>
|
<div class='card-content'>
|
||||||
<div class='device-picker'>
|
<div class='device-picker'>
|
||||||
<paper-dropdown-menu
|
<paper-dropdown-menu
|
||||||
label='Device'
|
label='[[label]]'
|
||||||
class='flex'
|
class='flex'
|
||||||
disabled='[[!entities.length]]'
|
disabled='[[!entities.length]]'
|
||||||
>
|
>
|
||||||
@ -61,6 +66,13 @@
|
|||||||
on-tap='saveEntity'
|
on-tap='saveEntity'
|
||||||
disabled='[[computeShowPlaceholder(formState)]]'
|
disabled='[[computeShowPlaceholder(formState)]]'
|
||||||
>SAVE</paper-button>
|
>SAVE</paper-button>
|
||||||
|
<template is='dom-if' if='[[allowDelete]]'>
|
||||||
|
<paper-button
|
||||||
|
class='warning'
|
||||||
|
on-tap='deleteEntity'
|
||||||
|
disabled='[[computeShowPlaceholder(formState)]]'
|
||||||
|
>DELETE</paper-button>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</paper-card>
|
</paper-card>
|
||||||
|
|
||||||
@ -77,11 +89,21 @@ Polymer({
|
|||||||
observer: 'hassChanged',
|
observer: 'hassChanged',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
label: {
|
||||||
|
type: String,
|
||||||
|
value: 'Device',
|
||||||
|
},
|
||||||
|
|
||||||
entities: {
|
entities: {
|
||||||
type: Array,
|
type: Array,
|
||||||
observer: 'entitiesChanged',
|
observer: 'entitiesChanged',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
allowDelete: {
|
||||||
|
type: Boolean,
|
||||||
|
value: false,
|
||||||
|
},
|
||||||
|
|
||||||
selectedEntity: {
|
selectedEntity: {
|
||||||
type: Number,
|
type: Number,
|
||||||
value: -1,
|
value: -1,
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
.form-group {
|
.form-group {
|
||||||
@apply(--layout-horizontal);
|
@apply(--layout-horizontal);
|
||||||
@apply(--layout-center);
|
@apply(--layout-center);
|
||||||
padding: 4px 16px;
|
padding: 8px 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-group label {
|
.form-group label {
|
||||||
@ -14,6 +14,15 @@
|
|||||||
.form-group .form-control {
|
.form-group .form-control {
|
||||||
@apply(--layout-flex-1);
|
@apply(--layout-flex-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.form-group.vertical {
|
||||||
|
@apply(--layout-vertical);
|
||||||
|
@apply(--layout-start);
|
||||||
|
}
|
||||||
|
|
||||||
|
paper-dropdown-menu.form-control {
|
||||||
|
margin: -9px 0;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</template>
|
</template>
|
||||||
</dom-module>
|
</dom-module>
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
<link rel="import" href="../../src/components/ha-menu-button.html">
|
<link rel="import" href="../../src/components/ha-menu-button.html">
|
||||||
<link rel='import' href='../../bower_components/iron-media-query/iron-media-query.html'>
|
<link rel='import' href='../../bower_components/iron-media-query/iron-media-query.html'>
|
||||||
<link rel="import" href="./core/ha-config-section-core.html">
|
<link rel="import" href="./core/ha-config-section-core.html">
|
||||||
|
<link rel="import" href="./group/ha-config-section-group.html">
|
||||||
<link rel="import" href="./hassbian/ha-config-section-hassbian.html">
|
<link rel="import" href="./hassbian/ha-config-section-hassbian.html">
|
||||||
<link rel="import" href="./z-wave/ha-config-section-zwave.html">
|
<link rel="import" href="./z-wave/ha-config-section-zwave.html">
|
||||||
|
|
||||||
@ -38,6 +39,11 @@
|
|||||||
</app-header>
|
</app-header>
|
||||||
|
|
||||||
<div class$='[[computeClasses(isWide)]]'>
|
<div class$='[[computeClasses(isWide)]]'>
|
||||||
|
<ha-config-section-group
|
||||||
|
is-wide='[[isWide]]'
|
||||||
|
hass='[[hass]]'
|
||||||
|
></ha-config-section-group>
|
||||||
|
|
||||||
<ha-config-section-core
|
<ha-config-section-core
|
||||||
is-wide='[[isWide]]'
|
is-wide='[[isWide]]'
|
||||||
hass='[[hass]]'
|
hass='[[hass]]'
|
||||||
|
@ -64,9 +64,9 @@ Polymer({
|
|||||||
computeEntities: function (hass) {
|
computeEntities: function (hass) {
|
||||||
return Object.keys(hass.states)
|
return Object.keys(hass.states)
|
||||||
.map(function (key) { return hass.states[key]; })
|
.map(function (key) { return hass.states[key]; })
|
||||||
.filter(function (el) {
|
.filter(function (ent) {
|
||||||
return (!el.attributes.hidden &&
|
return (!ent.attributes.hidden &&
|
||||||
'node_id' in el.attributes);
|
'node_id' in ent.attributes);
|
||||||
})
|
})
|
||||||
.sort(function (entityA, entityB) {
|
.sort(function (entityA, entityB) {
|
||||||
if (entityA.entity_id < entityB.entity_id) {
|
if (entityA.entity_id < entityB.entity_id) {
|
||||||
|
@ -5,30 +5,6 @@
|
|||||||
<dom-module id="ha-form-zwave-device">
|
<dom-module id="ha-form-zwave-device">
|
||||||
<template>
|
<template>
|
||||||
<style include="iron-flex ha-style ha-form-style">
|
<style include="iron-flex ha-style ha-form-style">
|
||||||
.device-picker {
|
|
||||||
@apply(--layout-horizontal);
|
|
||||||
padding-bottom: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-placeholder {
|
|
||||||
@apply(--layout-vertical);
|
|
||||||
@apply(--layout-center-center);
|
|
||||||
height: 96px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-group {
|
|
||||||
@apply(--layout-horizontal);
|
|
||||||
@apply(--layout-center);
|
|
||||||
padding: 4px 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-group label {
|
|
||||||
@apply(--layout-flex-2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-group .form-control {
|
|
||||||
@apply(--layout-flex-1);
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
<div class='form-group'>
|
<div class='form-group'>
|
||||||
<paper-checkbox
|
<paper-checkbox
|
||||||
|
@ -90,6 +90,11 @@
|
|||||||
color: var(--default-primary-color);
|
color: var(--default-primary-color);
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card-actions > paper-button.warning:not([disabled]),
|
||||||
|
.card-actions > ha-call-service-button.warning:not([disabled]) {
|
||||||
|
color: var(--google-red-500);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</template>
|
</template>
|
||||||
</dom-module>
|
</dom-module>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user