mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-30 20:56:36 +00:00
Add Area Registry (#2631)
This commit is contained in:
parent
b86bfa0395
commit
f1f1623d2f
39
src/data/area_registry.ts
Normal file
39
src/data/area_registry.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import { HomeAssistant } from "../types";
|
||||
|
||||
export interface AreaRegistryEntry {
|
||||
area_id: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface AreaRegistryEntryMutableParams {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export const fetchAreaRegistry = (hass: HomeAssistant) =>
|
||||
hass.callWS<AreaRegistryEntry[]>({ type: "config/area_registry/list" });
|
||||
|
||||
export const createAreaRegistryEntry = (
|
||||
hass: HomeAssistant,
|
||||
values: AreaRegistryEntryMutableParams
|
||||
) =>
|
||||
hass.callWS<AreaRegistryEntry>({
|
||||
type: "config/area_registry/create",
|
||||
...values,
|
||||
});
|
||||
|
||||
export const updateAreaRegistryEntry = (
|
||||
hass: HomeAssistant,
|
||||
areaId: string,
|
||||
updates: Partial<AreaRegistryEntryMutableParams>
|
||||
) =>
|
||||
hass.callWS<AreaRegistryEntry>({
|
||||
type: "config/area_registry/update",
|
||||
area_id: areaId,
|
||||
...updates,
|
||||
});
|
||||
|
||||
export const deleteAreaRegistryEntry = (hass: HomeAssistant, areaId: string) =>
|
||||
hass.callWS({
|
||||
type: "config/area_registry/delete",
|
||||
area_id: areaId,
|
||||
});
|
31
src/data/device_registry.ts
Normal file
31
src/data/device_registry.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { HomeAssistant } from "../types";
|
||||
|
||||
export interface DeviceRegistryEntry {
|
||||
id: string;
|
||||
config_entries: string[];
|
||||
connections: Array<[string, string]>;
|
||||
manufacturer: string;
|
||||
model?: string;
|
||||
name?: string;
|
||||
sw_version?: string;
|
||||
hub_device_id?: string;
|
||||
area_id?: string;
|
||||
}
|
||||
|
||||
export interface DeviceRegistryEntryMutableParams {
|
||||
area_id: string;
|
||||
}
|
||||
|
||||
export const fetchDeviceRegistry = (hass: HomeAssistant) =>
|
||||
hass.callWS<DeviceRegistryEntry[]>({ type: "config/device_registry/list" });
|
||||
|
||||
export const updateDeviceRegistryEntry = (
|
||||
hass: HomeAssistant,
|
||||
deviceId: string,
|
||||
updates: Partial<DeviceRegistryEntryMutableParams>
|
||||
) =>
|
||||
hass.callWS<DeviceRegistryEntry>({
|
||||
type: "config/device_registry/update",
|
||||
device_id: deviceId,
|
||||
...updates,
|
||||
});
|
160
src/panels/config/area_registry/dialog-area-registry-detail.ts
Normal file
160
src/panels/config/area_registry/dialog-area-registry-detail.ts
Normal file
@ -0,0 +1,160 @@
|
||||
import {
|
||||
LitElement,
|
||||
html,
|
||||
css,
|
||||
PropertyDeclarations,
|
||||
CSSResult,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import "@polymer/paper-dialog/paper-dialog";
|
||||
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
|
||||
import "@polymer/paper-input/paper-input";
|
||||
|
||||
import { AreaRegistryDetailDialogParams } from "./show-dialog-area-registry-detail";
|
||||
import { PolymerChangedEvent } from "../../../polymer-types";
|
||||
import { haStyleDialog } from "../../../resources/ha-style";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { AreaRegistryEntryMutableParams } from "../../../data/area_registry";
|
||||
|
||||
class DialogAreaDetail extends LitElement {
|
||||
public hass!: HomeAssistant;
|
||||
private _name!: string;
|
||||
private _error?: string;
|
||||
private _params?: AreaRegistryDetailDialogParams;
|
||||
private _submitting?: boolean;
|
||||
|
||||
static get properties(): PropertyDeclarations {
|
||||
return {
|
||||
_error: {},
|
||||
_name: {},
|
||||
_params: {},
|
||||
};
|
||||
}
|
||||
|
||||
public async showDialog(
|
||||
params: AreaRegistryDetailDialogParams
|
||||
): Promise<void> {
|
||||
this._params = params;
|
||||
this._error = undefined;
|
||||
this._name = this._params.entry ? this._params.entry.name : "";
|
||||
await this.updateComplete;
|
||||
}
|
||||
|
||||
protected render(): TemplateResult | void {
|
||||
if (!this._params) {
|
||||
return html``;
|
||||
}
|
||||
const nameInvalid = this._name.trim() === "";
|
||||
return html`
|
||||
<paper-dialog
|
||||
with-backdrop
|
||||
opened
|
||||
@opened-changed="${this._openedChanged}"
|
||||
>
|
||||
<h2>${this._params.entry ? this._params.entry.name : "New Area"}</h2>
|
||||
<paper-dialog-scrollable>
|
||||
${this._error
|
||||
? html`
|
||||
<div class="error">${this._error}</div>
|
||||
`
|
||||
: ""}
|
||||
<div class="form">
|
||||
<paper-input
|
||||
.value=${this._name}
|
||||
@value-changed=${this._nameChanged}
|
||||
label="Name"
|
||||
error-message="Name is required"
|
||||
.invalid=${nameInvalid}
|
||||
></paper-input>
|
||||
</div>
|
||||
</paper-dialog-scrollable>
|
||||
<div class="paper-dialog-buttons">
|
||||
${this._params.entry
|
||||
? html`
|
||||
<paper-button
|
||||
class="danger"
|
||||
@click="${this._deleteEntry}"
|
||||
.disabled=${this._submitting}
|
||||
>
|
||||
DELETE
|
||||
</paper-button>
|
||||
`
|
||||
: html``}
|
||||
<paper-button
|
||||
@click="${this._updateEntry}"
|
||||
.disabled=${nameInvalid || this._submitting}
|
||||
>
|
||||
${this._params.entry ? "UPDATE" : "CREATE"}
|
||||
</paper-button>
|
||||
</div>
|
||||
</paper-dialog>
|
||||
`;
|
||||
}
|
||||
|
||||
private _nameChanged(ev: PolymerChangedEvent<string>) {
|
||||
this._error = undefined;
|
||||
this._name = ev.detail.value;
|
||||
}
|
||||
|
||||
private async _updateEntry() {
|
||||
try {
|
||||
const values: AreaRegistryEntryMutableParams = {
|
||||
name: this._name.trim(),
|
||||
};
|
||||
if (this._params!.entry) {
|
||||
await this._params!.updateEntry(values);
|
||||
} else {
|
||||
await this._params!.createEntry(values);
|
||||
}
|
||||
this._params = undefined;
|
||||
} catch (err) {
|
||||
this._error = err;
|
||||
}
|
||||
}
|
||||
|
||||
private async _deleteEntry() {
|
||||
if (await this._params!.removeEntry()) {
|
||||
this._params = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
private _openedChanged(ev: PolymerChangedEvent<boolean>): void {
|
||||
if (!(ev.detail as any).value) {
|
||||
this._params = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [
|
||||
haStyleDialog,
|
||||
css`
|
||||
paper-dialog {
|
||||
min-width: 400px;
|
||||
}
|
||||
.form {
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
paper-button {
|
||||
font-weight: 500;
|
||||
}
|
||||
paper-button.danger {
|
||||
font-weight: 500;
|
||||
color: var(--google-red-500);
|
||||
margin-left: -12px;
|
||||
margin-right: auto;
|
||||
}
|
||||
.error {
|
||||
color: var(--google-red-500);
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"dialog-area-registry-detail": DialogAreaDetail;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("dialog-area-registry-detail", DialogAreaDetail);
|
190
src/panels/config/area_registry/ha-config-area-registry.ts
Normal file
190
src/panels/config/area_registry/ha-config-area-registry.ts
Normal file
@ -0,0 +1,190 @@
|
||||
import {
|
||||
LitElement,
|
||||
TemplateResult,
|
||||
html,
|
||||
css,
|
||||
CSSResult,
|
||||
PropertyDeclarations,
|
||||
} from "lit-element";
|
||||
import "@polymer/paper-item/paper-item";
|
||||
import "@polymer/paper-item/paper-item-body";
|
||||
import "@polymer/paper-card/paper-card";
|
||||
import "@polymer/paper-fab/paper-fab";
|
||||
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import {
|
||||
AreaRegistryEntry,
|
||||
fetchAreaRegistry,
|
||||
updateAreaRegistryEntry,
|
||||
deleteAreaRegistryEntry,
|
||||
createAreaRegistryEntry,
|
||||
} from "../../../data/area_registry";
|
||||
import "../../../layouts/hass-subpage";
|
||||
import "../../../layouts/hass-loading-screen";
|
||||
import compare from "../../../common/string/compare";
|
||||
import "../ha-config-section";
|
||||
import {
|
||||
showAreaRegistryDetailDialog,
|
||||
loadAreaRegistryDetailDialog,
|
||||
} from "./show-dialog-area-registry-detail";
|
||||
|
||||
class HaConfigAreaRegistry extends LitElement {
|
||||
public hass?: HomeAssistant;
|
||||
public isWide?: boolean;
|
||||
private _items?: AreaRegistryEntry[];
|
||||
|
||||
static get properties(): PropertyDeclarations {
|
||||
return {
|
||||
hass: {},
|
||||
isWide: {},
|
||||
_items: {},
|
||||
};
|
||||
}
|
||||
|
||||
protected render(): TemplateResult | void {
|
||||
if (!this.hass || this._items === undefined) {
|
||||
return html`
|
||||
<hass-loading-screen></hass-loading-screen>
|
||||
`;
|
||||
}
|
||||
return html`
|
||||
<hass-subpage header="Area Registry">
|
||||
<ha-config-section .isWide=${this.isWide}>
|
||||
<span slot="header">Area Registry</span>
|
||||
<span slot="introduction">
|
||||
Areas are used to organize where devices are. This information will
|
||||
be used throughout Home Assistant to help you in organizing your
|
||||
interface, permissions and integrations with other systems.
|
||||
<p>
|
||||
To place devices in an area, navigate to
|
||||
<a href="/config/integrations">the integrations page</a> and then
|
||||
click on a configured integration to get to the device cards.
|
||||
</p>
|
||||
</span>
|
||||
<paper-card>
|
||||
${this._items.map((entry) => {
|
||||
return html`
|
||||
<paper-item @click=${this._openEditEntry} .entry=${entry}>
|
||||
<paper-item-body>
|
||||
${entry.name}
|
||||
</paper-item-body>
|
||||
</paper-item>
|
||||
`;
|
||||
})}
|
||||
${this._items.length === 0
|
||||
? html`
|
||||
<div class="empty">
|
||||
Looks like you have no areas yet!
|
||||
<paper-button @click=${this._createArea}>
|
||||
CREATE AREA</paper-button
|
||||
>
|
||||
</div>
|
||||
`
|
||||
: html``}
|
||||
</paper-card>
|
||||
</ha-config-section>
|
||||
</hass-subpage>
|
||||
|
||||
<paper-fab
|
||||
?is-wide=${this.isWide}
|
||||
icon="hass:plus"
|
||||
title="Create Area"
|
||||
@click=${this._createArea}
|
||||
></paper-fab>
|
||||
`;
|
||||
}
|
||||
|
||||
protected firstUpdated(changedProps) {
|
||||
super.firstUpdated(changedProps);
|
||||
this._fetchData();
|
||||
loadAreaRegistryDetailDialog();
|
||||
}
|
||||
|
||||
private async _fetchData() {
|
||||
this._items = (await fetchAreaRegistry(this.hass!)).sort((ent1, ent2) =>
|
||||
compare(ent1.name, ent2.name)
|
||||
);
|
||||
}
|
||||
|
||||
private _createArea() {
|
||||
this._openDialog();
|
||||
}
|
||||
|
||||
private _openEditEntry(ev: MouseEvent) {
|
||||
const entry: AreaRegistryEntry = (ev.currentTarget! as any).entry;
|
||||
this._openDialog(entry);
|
||||
}
|
||||
private _openDialog(entry?: AreaRegistryEntry) {
|
||||
showAreaRegistryDetailDialog(this, {
|
||||
entry,
|
||||
createEntry: async (values) => {
|
||||
const created = await createAreaRegistryEntry(this.hass!, values);
|
||||
this._items = this._items!.concat(created).sort((ent1, ent2) =>
|
||||
compare(ent1.name, ent2.name)
|
||||
);
|
||||
},
|
||||
updateEntry: async (values) => {
|
||||
const updated = await updateAreaRegistryEntry(
|
||||
this.hass!,
|
||||
entry!.area_id,
|
||||
values
|
||||
);
|
||||
this._items = this._items!.map((ent) =>
|
||||
ent === entry ? updated : ent
|
||||
);
|
||||
},
|
||||
removeEntry: async () => {
|
||||
if (
|
||||
!confirm(`Are you sure you want to delete this area?
|
||||
|
||||
All devices in this area will become unassigned.`)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
await deleteAreaRegistryEntry(this.hass!, entry!.area_id);
|
||||
this._items = this._items!.filter((ent) => ent !== entry);
|
||||
return true;
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
static get styles(): CSSResult {
|
||||
return css`
|
||||
a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
paper-card {
|
||||
display: block;
|
||||
max-width: 600px;
|
||||
margin: 16px auto;
|
||||
background-color: white;
|
||||
}
|
||||
.empty {
|
||||
text-align: center;
|
||||
}
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
paper-fab {
|
||||
position: fixed;
|
||||
bottom: 16px;
|
||||
right: 16px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
paper-fab[is-wide] {
|
||||
bottom: 24px;
|
||||
right: 24px;
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("ha-config-area-registry", HaConfigAreaRegistry);
|
@ -0,0 +1,28 @@
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import {
|
||||
AreaRegistryEntry,
|
||||
AreaRegistryEntryMutableParams,
|
||||
} from "../../../data/area_registry";
|
||||
|
||||
export interface AreaRegistryDetailDialogParams {
|
||||
entry?: AreaRegistryEntry;
|
||||
createEntry: (values: AreaRegistryEntryMutableParams) => Promise<unknown>;
|
||||
updateEntry: (
|
||||
updates: Partial<AreaRegistryEntryMutableParams>
|
||||
) => Promise<unknown>;
|
||||
removeEntry: () => Promise<boolean>;
|
||||
}
|
||||
|
||||
export const loadAreaRegistryDetailDialog = () =>
|
||||
import(/* webpackChunkName: "entity-registry-detail-dialog" */ "./dialog-area-registry-detail");
|
||||
|
||||
export const showAreaRegistryDetailDialog = (
|
||||
element: HTMLElement,
|
||||
systemLogDetailParams: AreaRegistryDetailDialogParams
|
||||
): void => {
|
||||
fireEvent(element, "show-dialog", {
|
||||
dialogTag: "dialog-area-registry-detail",
|
||||
dialogImport: loadAreaRegistryDetailDialog,
|
||||
dialogParams: systemLogDetailParams,
|
||||
});
|
||||
};
|
@ -8,6 +8,7 @@ import "./ha-config-entries-dashboard";
|
||||
import "./ha-config-entry-page";
|
||||
import NavigateMixin from "../../../mixins/navigate-mixin";
|
||||
import compare from "../../../common/string/compare";
|
||||
import { fetchAreaRegistry } from "../../../data/area_registry";
|
||||
|
||||
class HaConfigEntries extends NavigateMixin(PolymerElement) {
|
||||
static get template() {
|
||||
@ -23,6 +24,7 @@ class HaConfigEntries extends NavigateMixin(PolymerElement) {
|
||||
<ha-config-entry-page
|
||||
hass="[[hass]]"
|
||||
config-entry="[[_configEntry]]"
|
||||
areas="[[_areas]]"
|
||||
entries="[[_entries]]"
|
||||
entities="[[_entities]]"
|
||||
devices="[[_devices]]"
|
||||
@ -68,6 +70,11 @@ class HaConfigEntries extends NavigateMixin(PolymerElement) {
|
||||
*/
|
||||
_devices: Array,
|
||||
|
||||
/**
|
||||
* Area Registry entries.
|
||||
*/
|
||||
_areas: Array,
|
||||
|
||||
/**
|
||||
* Current flows that are in progress and have not been started by a user.
|
||||
* For example, can be discovered devices that require more config.
|
||||
@ -136,6 +143,10 @@ class HaConfigEntries extends NavigateMixin(PolymerElement) {
|
||||
.then((devices) => {
|
||||
this._devices = devices;
|
||||
});
|
||||
|
||||
fetchAreaRegistry(this.hass).then((areas) => {
|
||||
this._areas = areas;
|
||||
});
|
||||
}
|
||||
|
||||
_computeConfigEntry(routeData, entries) {
|
||||
|
@ -53,6 +53,7 @@ class HaConfigEntryPage extends NavigateMixin(
|
||||
<ha-device-card
|
||||
class="card"
|
||||
hass="[[hass]]"
|
||||
areas="[[areas]]"
|
||||
devices="[[devices]]"
|
||||
device="[[device]]"
|
||||
entities="[[entities]]"
|
||||
@ -97,6 +98,11 @@ class HaConfigEntryPage extends NavigateMixin(
|
||||
computed: "_computeNoDeviceEntities(configEntry, entities)",
|
||||
},
|
||||
|
||||
/**
|
||||
* Area registry entries
|
||||
*/
|
||||
areas: Array,
|
||||
|
||||
/**
|
||||
* Device registry entries
|
||||
*/
|
||||
|
@ -1,6 +1,9 @@
|
||||
import "@polymer/paper-item/paper-icon-item";
|
||||
import "@polymer/paper-item/paper-item-body";
|
||||
import "@polymer/paper-card/paper-card";
|
||||
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";
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
|
||||
@ -11,6 +14,7 @@ import LocalizeMixin from "../../../mixins/localize-mixin";
|
||||
import computeStateName from "../../../common/entity/compute_state_name";
|
||||
import "../../../components/entity/state-badge";
|
||||
import compare from "../../../common/string/compare";
|
||||
import { updateDeviceRegistryEntry } from "../../../data/device_registry";
|
||||
|
||||
function computeEntityName(hass, entity) {
|
||||
if (entity.name) return entity.name;
|
||||
@ -68,6 +72,22 @@ class HaDeviceCard extends EventsMixin(LocalizeMixin(PolymerElement)) {
|
||||
[[localize('ui.panel.config.integrations.config_entry.manuf',
|
||||
'manufacturer', device.manufacturer)]]
|
||||
</div>
|
||||
<div class="area">
|
||||
<paper-dropdown-menu
|
||||
selected-item-label="{{selectedArea}}"
|
||||
label="Area"
|
||||
>
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
selected="[[_computeSelectedArea(areas, device)]]"
|
||||
>
|
||||
<paper-item>No Area</paper-item>
|
||||
<template is="dom-repeat" items="[[areas]]">
|
||||
<paper-item area="[[item]]">[[item.name]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
</div>
|
||||
<template is="dom-if" if="[[device.hub_device_id]]">
|
||||
<div class="extra-info">
|
||||
@ -111,6 +131,7 @@ class HaDeviceCard extends EventsMixin(LocalizeMixin(PolymerElement)) {
|
||||
return {
|
||||
device: Object,
|
||||
devices: Array,
|
||||
areas: Array,
|
||||
entities: Array,
|
||||
hass: Object,
|
||||
narrow: {
|
||||
@ -121,9 +142,43 @@ class HaDeviceCard extends EventsMixin(LocalizeMixin(PolymerElement)) {
|
||||
type: Array,
|
||||
computed: "_computeChildDevices(device, devices)",
|
||||
},
|
||||
selectedArea: {
|
||||
type: String,
|
||||
observer: "_selectedAreaChanged",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
_computeSelectedArea(areas, device) {
|
||||
if (!areas || !device || !device.area_id) {
|
||||
return 0;
|
||||
}
|
||||
// +1 because of "No Area" entry
|
||||
return areas.findIndex((area) => area.area_id === device.area_id) + 1;
|
||||
}
|
||||
|
||||
async _selectedAreaChanged(option) {
|
||||
// Selected Option will transition to '' before transitioning to new value
|
||||
if (option === "" || !this.device || !this.areas) {
|
||||
return;
|
||||
}
|
||||
const area =
|
||||
option === "No Area"
|
||||
? undefined
|
||||
: this.areas.find((ar) => ar.name === option);
|
||||
|
||||
if (
|
||||
(!area && !this.device.area_id) ||
|
||||
(area && area.area_id === this.device.area_id)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
await updateDeviceRegistryEntry(this.hass, this.device.id, {
|
||||
area_id: area ? area.area_id : null,
|
||||
});
|
||||
}
|
||||
|
||||
_computeChildDevices(device, devices) {
|
||||
return devices
|
||||
.filter((dev) => dev.hub_device_id === device.id)
|
||||
|
@ -10,7 +10,7 @@ import LocalizeMixin from "../../../mixins/localize-mixin";
|
||||
|
||||
import isComponentLoaded from "../../../common/config/is_component_loaded";
|
||||
|
||||
const CORE_PAGES = ["core", "customize", "entity_registry"];
|
||||
const CORE_PAGES = ["core", "customize", "entity_registry", "area_registry"];
|
||||
/*
|
||||
* @appliesMixin LocalizeMixin
|
||||
* @appliesMixin NavigateMixin
|
||||
@ -54,6 +54,7 @@ class HaConfigNavigation extends LocalizeMixin(NavigateMixin(PolymerElement)) {
|
||||
"core",
|
||||
"customize",
|
||||
"entity_registry",
|
||||
"area_registry",
|
||||
"automation",
|
||||
"script",
|
||||
"zha",
|
||||
|
@ -9,6 +9,7 @@ import isComponentLoaded from "../../common/config/is_component_loaded";
|
||||
import EventsMixin from "../../mixins/events-mixin";
|
||||
import NavigateMixin from "../../mixins/navigate-mixin";
|
||||
|
||||
import(/* webpackChunkName: "panel-config-area-registry" */ "./area_registry/ha-config-area-registry");
|
||||
import(/* webpackChunkName: "panel-config-automation" */ "./automation/ha-config-automation");
|
||||
import(/* webpackChunkName: "panel-config-cloud" */ "./cloud/ha-config-cloud");
|
||||
import(/* webpackChunkName: "panel-config-config" */ "./config-entries/ha-config-entries");
|
||||
@ -42,6 +43,19 @@ class HaPanelConfig extends EventsMixin(NavigateMixin(PolymerElement)) {
|
||||
>
|
||||
</iron-media-query>
|
||||
|
||||
<template
|
||||
is="dom-if"
|
||||
if='[[_equals(_routeData.page, "area_registry")]]'
|
||||
restamp
|
||||
>
|
||||
<ha-config-area-registry
|
||||
page-name="area_registry"
|
||||
route="[[route]]"
|
||||
hass="[[hass]]"
|
||||
is-wide="[[isWide]]"
|
||||
></ha-config-area-registry>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if='[[_equals(_routeData.page, "core")]]' restamp>
|
||||
<ha-config-core
|
||||
page-name="core"
|
||||
|
@ -527,6 +527,10 @@
|
||||
"config": {
|
||||
"header": "Configure Home Assistant",
|
||||
"introduction": "Here it is possible to configure your components and Home Assistant. Not everything is possible to configure from the UI yet, but we're working on it.",
|
||||
"area_registry": {
|
||||
"caption": "Area Registry",
|
||||
"description": "Overview of all areas in your home."
|
||||
},
|
||||
"core": {
|
||||
"caption": "General",
|
||||
"description": "Validate your configuration file and control the server",
|
||||
|
Loading…
x
Reference in New Issue
Block a user