mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-27 19:26:36 +00:00
Remove customize UI (#10632)
This commit is contained in:
parent
7d94615f47
commit
1e851e0e8c
@ -1,88 +0,0 @@
|
||||
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
||||
import { property } from "lit/decorators";
|
||||
import "../../../components/ha-card";
|
||||
import "../../../layouts/hass-loading-screen";
|
||||
import "../../../layouts/hass-tabs-subpage";
|
||||
import { haStyle } from "../../../resources/styles";
|
||||
import { HomeAssistant, Route } from "../../../types";
|
||||
import { documentationUrl } from "../../../util/documentation-url";
|
||||
import "../ha-config-section";
|
||||
import "../ha-entity-config";
|
||||
import { configSections } from "../ha-panel-config";
|
||||
import "./ha-form-customize";
|
||||
|
||||
class HaConfigCustomize extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property() public isWide?: boolean;
|
||||
|
||||
@property() public narrow?: boolean;
|
||||
|
||||
@property() public route!: Route;
|
||||
|
||||
@property() private _selectedEntityId = "";
|
||||
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
<hass-tabs-subpage
|
||||
.hass=${this.hass}
|
||||
.narrow=${this.narrow}
|
||||
.route=${this.route}
|
||||
back-path="/config"
|
||||
.tabs=${configSections.advanced}
|
||||
>
|
||||
<ha-config-section .isWide=${this.isWide}>
|
||||
<span slot="header">
|
||||
${this.hass.localize("ui.panel.config.customize.picker.header")}
|
||||
</span>
|
||||
<span slot="introduction">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.customize.picker.introduction"
|
||||
)}
|
||||
<br />
|
||||
<a
|
||||
href=${documentationUrl(
|
||||
this.hass,
|
||||
"/docs/configuration/customizing-devices/#customization-using-the-ui"
|
||||
)}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.customize.picker.documentation"
|
||||
)}
|
||||
</a>
|
||||
</span>
|
||||
<ha-entity-config
|
||||
.hass=${this.hass}
|
||||
.selectedEntityId=${this._selectedEntityId}
|
||||
>
|
||||
</ha-entity-config>
|
||||
</ha-config-section>
|
||||
</div>
|
||||
</hass-tabs-subpage>
|
||||
`;
|
||||
}
|
||||
|
||||
protected firstUpdated(changedProps) {
|
||||
super.firstUpdated(changedProps);
|
||||
|
||||
if (!this.route.path.includes("/edit/")) {
|
||||
return;
|
||||
}
|
||||
const routeSegments = this.route.path.split("/edit/");
|
||||
this._selectedEntityId = routeSegments.length > 1 ? routeSegments[1] : "";
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return [
|
||||
haStyle,
|
||||
css`
|
||||
a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
customElements.define("ha-config-customize", HaConfigCustomize);
|
@ -1,84 +0,0 @@
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
/* eslint-plugin-disable lit */
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
import "../../../components/ha-icon";
|
||||
import "../../../components/ha-icon-button";
|
||||
import hassAttributeUtil from "../../../util/hass-attributes-util";
|
||||
import "../ha-form-style";
|
||||
import "./types/ha-customize-array";
|
||||
import "./types/ha-customize-boolean";
|
||||
import "./types/ha-customize-icon";
|
||||
import "./types/ha-customize-key-value";
|
||||
import "./types/ha-customize-string";
|
||||
|
||||
class HaCustomizeAttribute extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-form-style">
|
||||
:host {
|
||||
display: block;
|
||||
position: relative;
|
||||
padding-right: 40px;
|
||||
}
|
||||
|
||||
.button {
|
||||
position: absolute;
|
||||
margin-top: -20px;
|
||||
top: 50%;
|
||||
right: 0;
|
||||
}
|
||||
</style>
|
||||
<div id="wrapper" class="form-group"></div>
|
||||
<ha-icon-button class="button" on-click="tapButton">
|
||||
<ha-icon icon="[[getIcon(item.secondary)]]"></ha-icon>
|
||||
</ha-icon-button>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
item: {
|
||||
type: Object,
|
||||
notify: true,
|
||||
observer: "itemObserver",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
tapButton() {
|
||||
if (this.item.secondary) {
|
||||
this.item = { ...this.item, secondary: false };
|
||||
} else {
|
||||
this.item = { ...this.item, closed: true };
|
||||
}
|
||||
}
|
||||
|
||||
getIcon(secondary) {
|
||||
return secondary ? "hass:pencil" : "hass:close";
|
||||
}
|
||||
|
||||
itemObserver(item) {
|
||||
const wrapper = this.$.wrapper;
|
||||
const tag = hassAttributeUtil.TYPE_TO_TAG[item.type].toUpperCase();
|
||||
let child;
|
||||
if (wrapper.lastChild && wrapper.lastChild.tagName === tag) {
|
||||
child = wrapper.lastChild;
|
||||
} else {
|
||||
if (wrapper.lastChild) {
|
||||
wrapper.removeChild(wrapper.lastChild);
|
||||
}
|
||||
// Creating an element with upper case works fine in Chrome, but in FF it doesn't immediately
|
||||
// become a defined Custom Element. Polymer does that in some later pass.
|
||||
this.$.child = child = document.createElement(tag.toLowerCase());
|
||||
child.className = "form-control";
|
||||
child.addEventListener("item-changed", () => {
|
||||
this.item = { ...child.item };
|
||||
});
|
||||
}
|
||||
child.setProperties({ item: this.item });
|
||||
if (child.parentNode === null) {
|
||||
wrapper.appendChild(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
customElements.define("ha-customize-attribute", HaCustomizeAttribute);
|
@ -1,34 +0,0 @@
|
||||
import { MutableData } from "@polymer/polymer/lib/mixins/mutable-data";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
/* eslint-plugin-disable lit */
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
import "./ha-customize-attribute";
|
||||
|
||||
class HaFormCustomizeAttributes extends MutableData(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<template is="dom-repeat" items="{{attributes}}" mutable-data="">
|
||||
<ha-customize-attribute item="{{item}}" hidden$="[[item.closed]]">
|
||||
</ha-customize-attribute>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
attributes: {
|
||||
type: Array,
|
||||
notify: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
customElements.define(
|
||||
"ha-form-customize-attributes",
|
||||
HaFormCustomizeAttributes
|
||||
);
|
@ -1,362 +0,0 @@
|
||||
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 { computeStateDomain } from "../../../common/entity/compute_state_domain";
|
||||
import LocalizeMixin from "../../../mixins/localize-mixin";
|
||||
import "../../../styles/polymer-ha-style";
|
||||
import { documentationUrl } from "../../../util/documentation-url";
|
||||
import hassAttributeUtil from "../../../util/hass-attributes-util";
|
||||
import "../ha-form-style";
|
||||
import "./ha-form-customize-attributes";
|
||||
|
||||
export class HaFormCustomize extends LocalizeMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style ha-form-style">
|
||||
.warning {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.attributes-text {
|
||||
padding-left: 20px;
|
||||
}
|
||||
</style>
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[computeShowWarning(localConfig, globalConfig)]]"
|
||||
>
|
||||
<div class="warning">
|
||||
[[localize('ui.panel.config.customize.warning.include_sentence')]]
|
||||
<a
|
||||
href="[[_computeDocumentationUrl(hass)]]"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>[[localize('ui.panel.config.customize.warning.include_link')]]</a
|
||||
>.<br />
|
||||
[[localize('ui.panel.config.customize.warning.not_applied')]]
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[hasLocalAttributes]]">
|
||||
<p class="attributes-text">
|
||||
[[localize('ui.panel.config.customize.attributes_customize')]]<br />
|
||||
</p>
|
||||
<ha-form-customize-attributes
|
||||
attributes="{{localAttributes}}"
|
||||
></ha-form-customize-attributes>
|
||||
</template>
|
||||
<template is="dom-if" if="[[hasGlobalAttributes]]">
|
||||
<p class="attributes-text">
|
||||
[[localize('ui.panel.config.customize.attributes_outside')]]<br />
|
||||
[[localize('ui.panel.config.customize.different_include')]]
|
||||
</p>
|
||||
<ha-form-customize-attributes
|
||||
attributes="{{globalAttributes}}"
|
||||
></ha-form-customize-attributes>
|
||||
</template>
|
||||
<template is="dom-if" if="[[hasExistingAttributes]]">
|
||||
<p class="attributes-text">
|
||||
[[localize('ui.panel.config.customize.attributes_set')]]<br />
|
||||
[[localize('ui.panel.config.customize.attributes_override')]]
|
||||
</p>
|
||||
<ha-form-customize-attributes
|
||||
attributes="{{existingAttributes}}"
|
||||
></ha-form-customize-attributes>
|
||||
</template>
|
||||
<template is="dom-if" if="[[hasNewAttributes]]">
|
||||
<p class="attributes-text">
|
||||
[[localize('ui.panel.config.customize.attributes_not_set')]]
|
||||
</p>
|
||||
<ha-form-customize-attributes
|
||||
attributes="{{newAttributes}}"
|
||||
></ha-form-customize-attributes>
|
||||
</template>
|
||||
<template is="dom-if" if="[[entity]]">
|
||||
<div class="form-group">
|
||||
<paper-dropdown-menu
|
||||
label="[[localize('ui.panel.config.customize.pick_attribute')]]"
|
||||
class="flex"
|
||||
dynamic-align=""
|
||||
>
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
selected="{{selectedNewAttribute}}"
|
||||
>
|
||||
<template
|
||||
is="dom-repeat"
|
||||
items="[[newAttributesOptions]]"
|
||||
as="option"
|
||||
>
|
||||
<paper-item>[[option]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
hass: {
|
||||
type: Object,
|
||||
},
|
||||
|
||||
entity: Object,
|
||||
|
||||
localAttributes: {
|
||||
type: Array,
|
||||
computed: "computeLocalAttributes(localConfig)",
|
||||
},
|
||||
hasLocalAttributes: Boolean,
|
||||
|
||||
globalAttributes: {
|
||||
type: Array,
|
||||
computed: "computeGlobalAttributes(localConfig, globalConfig)",
|
||||
},
|
||||
hasGlobalAttributes: Boolean,
|
||||
|
||||
existingAttributes: {
|
||||
type: Array,
|
||||
computed:
|
||||
"computeExistingAttributes(localConfig, globalConfig, entity)",
|
||||
},
|
||||
hasExistingAttributes: Boolean,
|
||||
|
||||
newAttributes: {
|
||||
type: Array,
|
||||
value: [],
|
||||
},
|
||||
hasNewAttributes: Boolean,
|
||||
|
||||
newAttributesOptions: Array,
|
||||
selectedNewAttribute: {
|
||||
type: Number,
|
||||
value: -1,
|
||||
observer: "selectedNewAttributeObserver",
|
||||
},
|
||||
|
||||
localConfig: Object,
|
||||
globalConfig: Object,
|
||||
};
|
||||
}
|
||||
|
||||
static get observers() {
|
||||
return [
|
||||
"attributesObserver(localAttributes.*, globalAttributes.*, existingAttributes.*, newAttributes.*)",
|
||||
];
|
||||
}
|
||||
|
||||
_initOpenObject(key, value, secondary, config) {
|
||||
return {
|
||||
attribute: key,
|
||||
value: value,
|
||||
closed: false,
|
||||
domain: computeStateDomain(this.entity),
|
||||
secondary: secondary,
|
||||
description: key,
|
||||
...config,
|
||||
};
|
||||
}
|
||||
|
||||
loadEntity(entity) {
|
||||
this.entity = entity;
|
||||
return this.hass
|
||||
.callApi("GET", "config/customize/config/" + entity.entity_id)
|
||||
.then((data) => {
|
||||
this.localConfig = data.local;
|
||||
this.globalConfig = data.global;
|
||||
this.newAttributes = [];
|
||||
});
|
||||
}
|
||||
|
||||
saveEntity() {
|
||||
const data = {};
|
||||
const attrs = this.localAttributes.concat(
|
||||
this.globalAttributes,
|
||||
this.existingAttributes,
|
||||
this.newAttributes
|
||||
);
|
||||
attrs.forEach((attr) => {
|
||||
if (
|
||||
attr.closed ||
|
||||
attr.secondary ||
|
||||
!attr.attribute ||
|
||||
attr.value === null ||
|
||||
attr.value === undefined
|
||||
)
|
||||
return;
|
||||
const value = attr.type === "json" ? JSON.parse(attr.value) : attr.value;
|
||||
if (value === null || value === undefined) return;
|
||||
data[attr.attribute] = value;
|
||||
});
|
||||
|
||||
const objectId = this.entity.entity_id;
|
||||
return this.hass.callApi(
|
||||
"POST",
|
||||
"config/customize/config/" + objectId,
|
||||
data
|
||||
);
|
||||
}
|
||||
|
||||
_computeSingleAttribute(key, value, secondary) {
|
||||
const config = hassAttributeUtil.LOGIC_STATE_ATTRIBUTES[key] || {
|
||||
type: hassAttributeUtil.UNKNOWN_TYPE,
|
||||
};
|
||||
return this._initOpenObject(
|
||||
key,
|
||||
config.type === "json" ? JSON.stringify(value) : value,
|
||||
secondary,
|
||||
config
|
||||
);
|
||||
}
|
||||
|
||||
_computeAttributes(config, keys, secondary) {
|
||||
return keys.map((key) =>
|
||||
this._computeSingleAttribute(key, config[key], secondary)
|
||||
);
|
||||
}
|
||||
|
||||
_computeDocumentationUrl(hass) {
|
||||
return documentationUrl(
|
||||
hass,
|
||||
"/docs/configuration/customizing-devices/#customization-using-the-ui"
|
||||
);
|
||||
}
|
||||
|
||||
computeLocalAttributes(localConfig) {
|
||||
if (!localConfig) return [];
|
||||
const localKeys = Object.keys(localConfig);
|
||||
const result = this._computeAttributes(localConfig, localKeys, false);
|
||||
return result;
|
||||
}
|
||||
|
||||
computeGlobalAttributes(localConfig, globalConfig) {
|
||||
if (!localConfig || !globalConfig) return [];
|
||||
const localKeys = Object.keys(localConfig);
|
||||
const globalKeys = Object.keys(globalConfig).filter(
|
||||
(key) => !localKeys.includes(key)
|
||||
);
|
||||
return this._computeAttributes(globalConfig, globalKeys, true);
|
||||
}
|
||||
|
||||
computeExistingAttributes(localConfig, globalConfig, entity) {
|
||||
if (!localConfig || !globalConfig || !entity) return [];
|
||||
const localKeys = Object.keys(localConfig);
|
||||
const globalKeys = Object.keys(globalConfig);
|
||||
const entityKeys = Object.keys(entity.attributes).filter(
|
||||
(key) => !localKeys.includes(key) && !globalKeys.includes(key)
|
||||
);
|
||||
return this._computeAttributes(entity.attributes, entityKeys, true);
|
||||
}
|
||||
|
||||
computeShowWarning(localConfig, globalConfig) {
|
||||
if (!localConfig || !globalConfig) return false;
|
||||
return Object.keys(localConfig).some(
|
||||
(key) =>
|
||||
JSON.stringify(globalConfig[key]) !== JSON.stringify(localConfig[key])
|
||||
);
|
||||
}
|
||||
|
||||
filterFromAttributes(attributes) {
|
||||
return (key) =>
|
||||
!attributes ||
|
||||
attributes.every((attr) => attr.attribute !== key || attr.closed);
|
||||
}
|
||||
|
||||
getNewAttributesOptions(
|
||||
localAttributes,
|
||||
globalAttributes,
|
||||
existingAttributes,
|
||||
newAttributes
|
||||
) {
|
||||
const knownKeys = Object.keys(hassAttributeUtil.LOGIC_STATE_ATTRIBUTES)
|
||||
.filter((key) => {
|
||||
const conf = hassAttributeUtil.LOGIC_STATE_ATTRIBUTES[key];
|
||||
return (
|
||||
conf &&
|
||||
(!conf.domains ||
|
||||
!this.entity ||
|
||||
conf.domains.includes(computeStateDomain(this.entity)))
|
||||
);
|
||||
})
|
||||
.filter(this.filterFromAttributes(localAttributes))
|
||||
.filter(this.filterFromAttributes(globalAttributes))
|
||||
.filter(this.filterFromAttributes(existingAttributes))
|
||||
.filter(this.filterFromAttributes(newAttributes));
|
||||
return knownKeys.sort().concat("Other");
|
||||
}
|
||||
|
||||
selectedNewAttributeObserver(selected) {
|
||||
if (selected < 0) return;
|
||||
const option = this.newAttributesOptions[selected];
|
||||
if (selected === this.newAttributesOptions.length - 1) {
|
||||
// The "Other" option.
|
||||
const attr = this._initOpenObject("", "", false /* secondary */, {
|
||||
type: hassAttributeUtil.ADD_TYPE,
|
||||
});
|
||||
this.push("newAttributes", attr);
|
||||
this.selectedNewAttribute = -1;
|
||||
return;
|
||||
}
|
||||
let result = this.localAttributes.findIndex(
|
||||
(attr) => attr.attribute === option
|
||||
);
|
||||
if (result >= 0) {
|
||||
this.set("localAttributes." + result + ".closed", false);
|
||||
this.selectedNewAttribute = -1;
|
||||
return;
|
||||
}
|
||||
result = this.globalAttributes.findIndex(
|
||||
(attr) => attr.attribute === option
|
||||
);
|
||||
if (result >= 0) {
|
||||
this.set("globalAttributes." + result + ".closed", false);
|
||||
this.selectedNewAttribute = -1;
|
||||
return;
|
||||
}
|
||||
result = this.existingAttributes.findIndex(
|
||||
(attr) => attr.attribute === option
|
||||
);
|
||||
if (result >= 0) {
|
||||
this.set("existingAttributes." + result + ".closed", false);
|
||||
this.selectedNewAttribute = -1;
|
||||
return;
|
||||
}
|
||||
result = this.newAttributes.findIndex((attr) => attr.attribute === option);
|
||||
if (result >= 0) {
|
||||
this.set("newAttributes." + result + ".closed", false);
|
||||
this.selectedNewAttribute = -1;
|
||||
return;
|
||||
}
|
||||
const attr = this._computeSingleAttribute(
|
||||
option,
|
||||
"",
|
||||
false /* secondary */
|
||||
);
|
||||
this.push("newAttributes", attr);
|
||||
this.selectedNewAttribute = -1;
|
||||
}
|
||||
|
||||
attributesObserver() {
|
||||
this.hasLocalAttributes =
|
||||
this.localAttributes && this.localAttributes.some((attr) => !attr.closed);
|
||||
this.hasGlobalAttributes =
|
||||
this.globalAttributes &&
|
||||
this.globalAttributes.some((attr) => !attr.closed);
|
||||
this.hasExistingAttributes =
|
||||
this.existingAttributes &&
|
||||
this.existingAttributes.some((attr) => !attr.closed);
|
||||
this.hasNewAttributes =
|
||||
this.newAttributes && this.newAttributes.some((attr) => !attr.closed);
|
||||
this.newAttributesOptions = this.getNewAttributesOptions(
|
||||
this.localAttributes,
|
||||
this.globalAttributes,
|
||||
this.existingAttributes,
|
||||
this.newAttributes
|
||||
);
|
||||
}
|
||||
}
|
||||
customElements.define("ha-form-customize", HaFormCustomize);
|
@ -1,63 +0,0 @@
|
||||
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 { EventsMixin } from "../../../../mixins/events-mixin";
|
||||
|
||||
/*
|
||||
* @appliesMixin EventsMixin
|
||||
*/
|
||||
class HaCustomizeArray extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
paper-dropdown-menu {
|
||||
margin: -9px 0;
|
||||
}
|
||||
</style>
|
||||
<paper-dropdown-menu
|
||||
label="[[item.description]]"
|
||||
disabled="[[item.secondary]]"
|
||||
selected-item-label="{{item.value}}"
|
||||
dynamic-align=""
|
||||
>
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
selected="[[computeSelected(item)]]"
|
||||
>
|
||||
<template is="dom-repeat" items="[[getOptions(item)]]" as="option">
|
||||
<paper-item>[[option]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
item: {
|
||||
type: Object,
|
||||
notifies: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
getOptions(item) {
|
||||
const domain = item.domain || "*";
|
||||
const options = item.options[domain] || item.options["*"];
|
||||
if (!options) {
|
||||
this.item.type = "string";
|
||||
this.fire("item-changed");
|
||||
return [];
|
||||
}
|
||||
return options.sort();
|
||||
}
|
||||
|
||||
computeSelected(item) {
|
||||
const options = this.getOptions(item);
|
||||
return options.indexOf(item.value);
|
||||
}
|
||||
}
|
||||
customElements.define("ha-customize-array", HaCustomizeArray);
|
@ -1,34 +0,0 @@
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
/* eslint-plugin-disable lit */
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
import "../../../../components/ha-checkbox";
|
||||
import "../../../../components/ha-formfield";
|
||||
|
||||
class HaCustomizeBoolean extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<ha-formfield label="[[item.description]]">
|
||||
<ha-checkbox
|
||||
disabled="[[item.secondary]]"
|
||||
checked="[[item.value]]"
|
||||
on-change="checkedChanged"
|
||||
>
|
||||
</ha-checkbox
|
||||
></ha-formfield>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
item: {
|
||||
type: Object,
|
||||
notifies: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
checkedChanged(ev) {
|
||||
this.item.value = ev.target.checked;
|
||||
}
|
||||
}
|
||||
customElements.define("ha-customize-boolean", HaCustomizeBoolean);
|
@ -1,40 +0,0 @@
|
||||
import "@polymer/paper-input/paper-input";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
/* eslint-plugin-disable lit */
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
import "../../../../components/ha-icon";
|
||||
|
||||
class HaCustomizeIcon extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
:host {
|
||||
@apply --layout-horizontal;
|
||||
}
|
||||
.icon-image {
|
||||
border: 1px solid grey;
|
||||
padding: 8px;
|
||||
margin-right: 20px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
</style>
|
||||
<ha-icon class="icon-image" icon="[[item.value]]"></ha-icon>
|
||||
<paper-input
|
||||
disabled="[[item.secondary]]"
|
||||
label="Icon"
|
||||
value="{{item.value}}"
|
||||
>
|
||||
</paper-input>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
item: {
|
||||
type: Object,
|
||||
notifies: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
customElements.define("ha-customize-icon", HaCustomizeIcon);
|
@ -1,45 +0,0 @@
|
||||
import "@polymer/paper-input/paper-input";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
/* eslint-plugin-disable lit */
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
|
||||
class HaCustomizeKeyValue extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
:host {
|
||||
@apply --layout-horizontal;
|
||||
}
|
||||
paper-input {
|
||||
@apply --layout-flex;
|
||||
}
|
||||
.key {
|
||||
padding-right: 20px;
|
||||
}
|
||||
</style>
|
||||
<paper-input
|
||||
disabled="[[item.secondary]]"
|
||||
class="key"
|
||||
label="Attribute name"
|
||||
value="{{item.attribute}}"
|
||||
>
|
||||
</paper-input>
|
||||
<paper-input
|
||||
disabled="[[item.secondary]]"
|
||||
label="Attribute value"
|
||||
value="{{item.value}}"
|
||||
>
|
||||
</paper-input>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
item: {
|
||||
type: Object,
|
||||
notifies: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
customElements.define("ha-customize-key-value", HaCustomizeKeyValue);
|
@ -1,35 +0,0 @@
|
||||
import "@polymer/paper-input/paper-input";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
/* eslint-plugin-disable lit */
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
import { formatAttributeName } from "../../../../util/hass-attributes-util";
|
||||
|
||||
class HaCustomizeString extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<paper-input
|
||||
disabled="[[item.secondary]]"
|
||||
label="[[getLabel(item)]]"
|
||||
value="{{item.value}}"
|
||||
>
|
||||
</paper-input>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
item: {
|
||||
type: Object,
|
||||
notifies: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
getLabel(item) {
|
||||
return (
|
||||
formatAttributeName(item.description) +
|
||||
(item.type === "json" ? " (JSON formatted)" : "")
|
||||
);
|
||||
}
|
||||
}
|
||||
customElements.define("ha-customize-string", HaCustomizeString);
|
@ -165,21 +165,6 @@ export class DialogEntityEditor extends LitElement {
|
||||
>${this.hass.localize("ui.dialogs.entity_registry.faq")}</a
|
||||
>`
|
||||
)}
|
||||
${this.hass.userData?.showAdvanced
|
||||
? html`<br /><br />
|
||||
${this.hass.localize(
|
||||
"ui.dialogs.entity_registry.info_customize",
|
||||
"customize_link",
|
||||
html`<a
|
||||
href=${"/config/customize/edit/" +
|
||||
this._params!.entity_id}
|
||||
rel="noreferrer"
|
||||
>${this.hass.localize(
|
||||
"ui.dialogs.entity_registry.customize_link"
|
||||
)}</a
|
||||
>`
|
||||
)}`
|
||||
: ""}
|
||||
</div>
|
||||
`;
|
||||
case "tab-related":
|
||||
|
@ -1,122 +0,0 @@
|
||||
import "@material/mwc-button";
|
||||
import {
|
||||
css,
|
||||
CSSResultGroup,
|
||||
html,
|
||||
LitElement,
|
||||
PropertyValues,
|
||||
TemplateResult,
|
||||
} from "lit";
|
||||
import { customElement, property, query } from "lit/decorators";
|
||||
import "../../components/buttons/ha-progress-button";
|
||||
import "../../components/entity/ha-entity-picker";
|
||||
import "../../components/ha-card";
|
||||
import "../../components/ha-circular-progress";
|
||||
import { haStyle } from "../../resources/styles";
|
||||
import "../../styles/polymer-ha-style";
|
||||
import type { HomeAssistant } from "../../types";
|
||||
import { HaFormCustomize } from "./customize/ha-form-customize";
|
||||
|
||||
@customElement("ha-entity-config")
|
||||
export class HaEntityConfig extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property() public selectedEntityId!: string;
|
||||
|
||||
// False if no entity is selected or currently saving or loading
|
||||
@property() private _formEditState = false;
|
||||
|
||||
@query("#form") private _form!: HaFormCustomize;
|
||||
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
<ha-card>
|
||||
<div class="card-content">
|
||||
<ha-entity-picker
|
||||
.hass=${this.hass}
|
||||
.value=${this.selectedEntityId}
|
||||
.configValue=${"entity"}
|
||||
@change=${this._selectedEntityChanged}
|
||||
allow-custom-entity
|
||||
hideClearIcon
|
||||
>
|
||||
</ha-entity-picker>
|
||||
|
||||
<div class="form-container">
|
||||
<ha-form-customize .hass=${this.hass} .id=${"form"}>
|
||||
</ha-form-customize>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-progress-button
|
||||
@click=${this._saveEntity}
|
||||
.disabled=${!this._formEditState}
|
||||
>
|
||||
${this.hass.localize("ui.common.save")}
|
||||
</ha-progress-button>
|
||||
</div>
|
||||
</ha-card>
|
||||
`;
|
||||
}
|
||||
|
||||
protected updated(changedProps: PropertyValues) {
|
||||
super.updated(changedProps);
|
||||
if (
|
||||
changedProps.has("selectedEntityId") &&
|
||||
changedProps.get("selectedEntityId") !== this.selectedEntityId
|
||||
) {
|
||||
this._selectEntity(this.selectedEntityId);
|
||||
this.requestUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
private _selectedEntityChanged(ev) {
|
||||
this._selectEntity(ev.target.value);
|
||||
}
|
||||
|
||||
private async _selectEntity(entityId?: string) {
|
||||
if (!this._form || !entityId) return;
|
||||
const entity = this.hass.states[entityId];
|
||||
if (!entity) return;
|
||||
|
||||
this._formEditState = false;
|
||||
await this._form.loadEntity(entity);
|
||||
this._formEditState = true;
|
||||
}
|
||||
|
||||
private async _saveEntity(ev) {
|
||||
if (!this._formEditState) return;
|
||||
this._formEditState = false;
|
||||
const button = ev.target;
|
||||
button.progress = true;
|
||||
|
||||
try {
|
||||
await this._form.saveEntity();
|
||||
this._formEditState = true;
|
||||
button.actionSuccess();
|
||||
} catch {
|
||||
button.actionError();
|
||||
} finally {
|
||||
button.progress = false;
|
||||
}
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return [
|
||||
haStyle,
|
||||
css`
|
||||
ha-card {
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
.form-placeholder {
|
||||
height: 96px;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
@ -10,7 +10,6 @@ import {
|
||||
mdiNfcVariant,
|
||||
mdiPalette,
|
||||
mdiPaletteSwatch,
|
||||
mdiPencil,
|
||||
mdiPuzzle,
|
||||
mdiRobot,
|
||||
mdiScriptText,
|
||||
@ -180,16 +179,6 @@ export const configSections: { [name: string]: PageNavigation[] } = {
|
||||
core: true,
|
||||
},
|
||||
],
|
||||
advanced: [
|
||||
{
|
||||
component: "customize",
|
||||
path: "/config/customize",
|
||||
translationKey: "ui.panel.config.customize.caption",
|
||||
iconPath: mdiPencil,
|
||||
core: true,
|
||||
advancedOnly: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@customElement("ha-panel-config")
|
||||
@ -243,10 +232,8 @@ class HaPanelConfig extends HassRouterPage {
|
||||
tag: "ha-config-info",
|
||||
load: () => import("./info/ha-config-info"),
|
||||
},
|
||||
customize: {
|
||||
tag: "ha-config-customize",
|
||||
load: () => import("./customize/ha-config-customize"),
|
||||
},
|
||||
// customize was removed in 2021.12, fallback to dashboard
|
||||
customize: "dashboard",
|
||||
dashboard: {
|
||||
tag: "ha-config-dashboard",
|
||||
load: () => import("./dashboard/ha-config-dashboard"),
|
||||
|
@ -141,7 +141,8 @@ const REDIRECTS: Redirects = {
|
||||
redirect: "/config/info",
|
||||
},
|
||||
customize: {
|
||||
redirect: "/config/customize",
|
||||
// customize was removed in 2021.12, fallback to dashboard
|
||||
redirect: "/config/dashboard",
|
||||
},
|
||||
profile: {
|
||||
redirect: "/profile/dashboard",
|
||||
|
@ -601,7 +601,6 @@
|
||||
"zone": "[%key:ui::panel::config::zone::caption%]",
|
||||
"users": "[%key:ui::panel::config::users::caption%]",
|
||||
"info": "[%key:ui::panel::config::info::caption%]",
|
||||
"customize": "[%key:ui::panel::config::customize::caption%]",
|
||||
"blueprint": "[%key:ui::panel::config::blueprint::caption%]",
|
||||
"server_control": "[%key:ui::panel::config::server_control::caption%]"
|
||||
}
|
||||
@ -687,8 +686,6 @@
|
||||
"dismiss": "Dismiss",
|
||||
"no_unique_id": "This entity (''{entity_id}'') does not have a unique ID, therefore its settings cannot be managed from the UI. See the {faq_link} for more detail.",
|
||||
"faq": "documentation",
|
||||
"info_customize": "You can overwrite some attributes in the {customize_link} section.",
|
||||
"customize_link": "entity customizations",
|
||||
"editor": {
|
||||
"name": "Name",
|
||||
"icon": "Icon",
|
||||
@ -1404,27 +1401,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"customize": {
|
||||
"caption": "Customizations",
|
||||
"description": "Customize your entities",
|
||||
"picker": {
|
||||
"header": "Customizations",
|
||||
"introduction": "Tweak per-entity attributes. Added/edited customizations will take effect immediately. Removed customizations will take effect when the entity is updated.",
|
||||
"documentation": "Customization documentation"
|
||||
},
|
||||
"warning": {
|
||||
"include_sentence": "It seems that your configuration.yaml doesn't properly",
|
||||
"include_link": "include customize.yaml",
|
||||
"not_applied": "Changes made here are written in it, but will not be applied after a configuration reload unless the include is in place."
|
||||
},
|
||||
"attributes_customize": "The following attributes are already set in customize.yaml",
|
||||
"attributes_outside": "The following attributes are customized from outside of customize.yaml",
|
||||
"different_include": "Possibly via a domain, a glob or a different include.",
|
||||
"attributes_set": "The following attributes of the entity are set programmatically.",
|
||||
"attributes_override": "You can override them if you like.",
|
||||
"attributes_not_set": "The following attributes weren't set. Set them if you like.",
|
||||
"pick_attribute": "Pick an attribute to override"
|
||||
},
|
||||
"automation": {
|
||||
"caption": "Automations",
|
||||
"description": "Create custom behavior rules for your home",
|
||||
|
Loading…
x
Reference in New Issue
Block a user