Remove customize UI (#10632)

This commit is contained in:
Joakim Sørensen 2021-11-17 19:34:20 +01:00 committed by GitHub
parent 7d94615f47
commit 1e851e0e8c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 4 additions and 962 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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
);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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":

View File

@ -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;
}
`,
];
}
}

View File

@ -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"),

View File

@ -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",

View File

@ -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",