mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-23 17:26:42 +00:00
Configuration Menu Updates 3 (#12377)
This commit is contained in:
parent
3677c5be2c
commit
9706c56c5c
@ -1,165 +1,167 @@
|
|||||||
|
export const currencies = [
|
||||||
|
"AED",
|
||||||
|
"AFN",
|
||||||
|
"ALL",
|
||||||
|
"AMD",
|
||||||
|
"ANG",
|
||||||
|
"AOA",
|
||||||
|
"ARS",
|
||||||
|
"AUD",
|
||||||
|
"AWG",
|
||||||
|
"AZN",
|
||||||
|
"BAM",
|
||||||
|
"BBD",
|
||||||
|
"BDT",
|
||||||
|
"BGN",
|
||||||
|
"BHD",
|
||||||
|
"BIF",
|
||||||
|
"BMD",
|
||||||
|
"BND",
|
||||||
|
"BOB",
|
||||||
|
"BRL",
|
||||||
|
"BSD",
|
||||||
|
"BTN",
|
||||||
|
"BWP",
|
||||||
|
"BYN",
|
||||||
|
"BYR",
|
||||||
|
"BZD",
|
||||||
|
"CAD",
|
||||||
|
"CDF",
|
||||||
|
"CHF",
|
||||||
|
"CLP",
|
||||||
|
"CNY",
|
||||||
|
"COP",
|
||||||
|
"CRC",
|
||||||
|
"CUP",
|
||||||
|
"CVE",
|
||||||
|
"CZK",
|
||||||
|
"DJF",
|
||||||
|
"DKK",
|
||||||
|
"DOP",
|
||||||
|
"DZD",
|
||||||
|
"EGP",
|
||||||
|
"ERN",
|
||||||
|
"ETB",
|
||||||
|
"EUR",
|
||||||
|
"FJD",
|
||||||
|
"FKP",
|
||||||
|
"GBP",
|
||||||
|
"GEL",
|
||||||
|
"GHS",
|
||||||
|
"GIP",
|
||||||
|
"GMD",
|
||||||
|
"GNF",
|
||||||
|
"GTQ",
|
||||||
|
"GYD",
|
||||||
|
"HKD",
|
||||||
|
"HNL",
|
||||||
|
"HRK",
|
||||||
|
"HTG",
|
||||||
|
"HUF",
|
||||||
|
"IDR",
|
||||||
|
"ILS",
|
||||||
|
"INR",
|
||||||
|
"IQD",
|
||||||
|
"IRR",
|
||||||
|
"ISK",
|
||||||
|
"JMD",
|
||||||
|
"JOD",
|
||||||
|
"JPY",
|
||||||
|
"KES",
|
||||||
|
"KGS",
|
||||||
|
"KHR",
|
||||||
|
"KMF",
|
||||||
|
"KPW",
|
||||||
|
"KRW",
|
||||||
|
"KWD",
|
||||||
|
"KYD",
|
||||||
|
"KZT",
|
||||||
|
"LAK",
|
||||||
|
"LBP",
|
||||||
|
"LKR",
|
||||||
|
"LRD",
|
||||||
|
"LSL",
|
||||||
|
"LTL",
|
||||||
|
"LYD",
|
||||||
|
"MAD",
|
||||||
|
"MDL",
|
||||||
|
"MGA",
|
||||||
|
"MKD",
|
||||||
|
"MMK",
|
||||||
|
"MNT",
|
||||||
|
"MOP",
|
||||||
|
"MRO",
|
||||||
|
"MUR",
|
||||||
|
"MVR",
|
||||||
|
"MWK",
|
||||||
|
"MXN",
|
||||||
|
"MYR",
|
||||||
|
"MZN",
|
||||||
|
"NAD",
|
||||||
|
"NGN",
|
||||||
|
"NIO",
|
||||||
|
"NOK",
|
||||||
|
"NPR",
|
||||||
|
"NZD",
|
||||||
|
"OMR",
|
||||||
|
"PAB",
|
||||||
|
"PEN",
|
||||||
|
"PGK",
|
||||||
|
"PHP",
|
||||||
|
"PKR",
|
||||||
|
"PLN",
|
||||||
|
"PYG",
|
||||||
|
"QAR",
|
||||||
|
"RON",
|
||||||
|
"RSD",
|
||||||
|
"RUB",
|
||||||
|
"RWF",
|
||||||
|
"SAR",
|
||||||
|
"SBD",
|
||||||
|
"SCR",
|
||||||
|
"SDG",
|
||||||
|
"SEK",
|
||||||
|
"SGD",
|
||||||
|
"SHP",
|
||||||
|
"SLL",
|
||||||
|
"SOS",
|
||||||
|
"SRD",
|
||||||
|
"SSP",
|
||||||
|
"STD",
|
||||||
|
"SYP",
|
||||||
|
"SZL",
|
||||||
|
"THB",
|
||||||
|
"TJS",
|
||||||
|
"TMT",
|
||||||
|
"TND",
|
||||||
|
"TOP",
|
||||||
|
"TRY",
|
||||||
|
"TTD",
|
||||||
|
"TWD",
|
||||||
|
"TZS",
|
||||||
|
"UAH",
|
||||||
|
"UGX",
|
||||||
|
"USD",
|
||||||
|
"UYU",
|
||||||
|
"UZS",
|
||||||
|
"VEF",
|
||||||
|
"VND",
|
||||||
|
"VUV",
|
||||||
|
"WST",
|
||||||
|
"XAF",
|
||||||
|
"XCD",
|
||||||
|
"XOF",
|
||||||
|
"XPF",
|
||||||
|
"YER",
|
||||||
|
"ZAR",
|
||||||
|
"ZMK",
|
||||||
|
"ZWL",
|
||||||
|
];
|
||||||
|
|
||||||
export const createCurrencyListEl = () => {
|
export const createCurrencyListEl = () => {
|
||||||
const list = document.createElement("datalist");
|
const list = document.createElement("datalist");
|
||||||
list.id = "currencies";
|
list.id = "currencies";
|
||||||
for (const currency of [
|
for (const currency of currencies) {
|
||||||
"AED",
|
|
||||||
"AFN",
|
|
||||||
"ALL",
|
|
||||||
"AMD",
|
|
||||||
"ANG",
|
|
||||||
"AOA",
|
|
||||||
"ARS",
|
|
||||||
"AUD",
|
|
||||||
"AWG",
|
|
||||||
"AZN",
|
|
||||||
"BAM",
|
|
||||||
"BBD",
|
|
||||||
"BDT",
|
|
||||||
"BGN",
|
|
||||||
"BHD",
|
|
||||||
"BIF",
|
|
||||||
"BMD",
|
|
||||||
"BND",
|
|
||||||
"BOB",
|
|
||||||
"BRL",
|
|
||||||
"BSD",
|
|
||||||
"BTN",
|
|
||||||
"BWP",
|
|
||||||
"BYN",
|
|
||||||
"BYR",
|
|
||||||
"BZD",
|
|
||||||
"CAD",
|
|
||||||
"CDF",
|
|
||||||
"CHF",
|
|
||||||
"CLP",
|
|
||||||
"CNY",
|
|
||||||
"COP",
|
|
||||||
"CRC",
|
|
||||||
"CUP",
|
|
||||||
"CVE",
|
|
||||||
"CZK",
|
|
||||||
"DJF",
|
|
||||||
"DKK",
|
|
||||||
"DOP",
|
|
||||||
"DZD",
|
|
||||||
"EGP",
|
|
||||||
"ERN",
|
|
||||||
"ETB",
|
|
||||||
"EUR",
|
|
||||||
"FJD",
|
|
||||||
"FKP",
|
|
||||||
"GBP",
|
|
||||||
"GEL",
|
|
||||||
"GHS",
|
|
||||||
"GIP",
|
|
||||||
"GMD",
|
|
||||||
"GNF",
|
|
||||||
"GTQ",
|
|
||||||
"GYD",
|
|
||||||
"HKD",
|
|
||||||
"HNL",
|
|
||||||
"HRK",
|
|
||||||
"HTG",
|
|
||||||
"HUF",
|
|
||||||
"IDR",
|
|
||||||
"ILS",
|
|
||||||
"INR",
|
|
||||||
"IQD",
|
|
||||||
"IRR",
|
|
||||||
"ISK",
|
|
||||||
"JMD",
|
|
||||||
"JOD",
|
|
||||||
"JPY",
|
|
||||||
"KES",
|
|
||||||
"KGS",
|
|
||||||
"KHR",
|
|
||||||
"KMF",
|
|
||||||
"KPW",
|
|
||||||
"KRW",
|
|
||||||
"KWD",
|
|
||||||
"KYD",
|
|
||||||
"KZT",
|
|
||||||
"LAK",
|
|
||||||
"LBP",
|
|
||||||
"LKR",
|
|
||||||
"LRD",
|
|
||||||
"LSL",
|
|
||||||
"LTL",
|
|
||||||
"LYD",
|
|
||||||
"MAD",
|
|
||||||
"MDL",
|
|
||||||
"MGA",
|
|
||||||
"MKD",
|
|
||||||
"MMK",
|
|
||||||
"MNT",
|
|
||||||
"MOP",
|
|
||||||
"MRO",
|
|
||||||
"MUR",
|
|
||||||
"MVR",
|
|
||||||
"MWK",
|
|
||||||
"MXN",
|
|
||||||
"MYR",
|
|
||||||
"MZN",
|
|
||||||
"NAD",
|
|
||||||
"NGN",
|
|
||||||
"NIO",
|
|
||||||
"NOK",
|
|
||||||
"NPR",
|
|
||||||
"NZD",
|
|
||||||
"OMR",
|
|
||||||
"PAB",
|
|
||||||
"PEN",
|
|
||||||
"PGK",
|
|
||||||
"PHP",
|
|
||||||
"PKR",
|
|
||||||
"PLN",
|
|
||||||
"PYG",
|
|
||||||
"QAR",
|
|
||||||
"RON",
|
|
||||||
"RSD",
|
|
||||||
"RUB",
|
|
||||||
"RWF",
|
|
||||||
"SAR",
|
|
||||||
"SBD",
|
|
||||||
"SCR",
|
|
||||||
"SDG",
|
|
||||||
"SEK",
|
|
||||||
"SGD",
|
|
||||||
"SHP",
|
|
||||||
"SLL",
|
|
||||||
"SOS",
|
|
||||||
"SRD",
|
|
||||||
"SSP",
|
|
||||||
"STD",
|
|
||||||
"SYP",
|
|
||||||
"SZL",
|
|
||||||
"THB",
|
|
||||||
"TJS",
|
|
||||||
"TMT",
|
|
||||||
"TND",
|
|
||||||
"TOP",
|
|
||||||
"TRY",
|
|
||||||
"TTD",
|
|
||||||
"TWD",
|
|
||||||
"TZS",
|
|
||||||
"UAH",
|
|
||||||
"UGX",
|
|
||||||
"USD",
|
|
||||||
"UYU",
|
|
||||||
"UZS",
|
|
||||||
"VEF",
|
|
||||||
"VND",
|
|
||||||
"VUV",
|
|
||||||
"WST",
|
|
||||||
"XAF",
|
|
||||||
"XCD",
|
|
||||||
"XOF",
|
|
||||||
"XPF",
|
|
||||||
"YER",
|
|
||||||
"ZAR",
|
|
||||||
"ZMK",
|
|
||||||
"ZWL",
|
|
||||||
]) {
|
|
||||||
const option = document.createElement("option");
|
const option = document.createElement("option");
|
||||||
option.value = currency;
|
option.value = currency;
|
||||||
option.innerHTML = currency;
|
option.innerHTML = currency;
|
||||||
|
77
src/components/ha-metric.ts
Normal file
77
src/components/ha-metric.ts
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
||||||
|
import { customElement, property } from "lit/decorators";
|
||||||
|
import { classMap } from "lit/directives/class-map";
|
||||||
|
import { roundWithOneDecimal } from "../util/calculate";
|
||||||
|
import "./ha-bar";
|
||||||
|
import "./ha-settings-row";
|
||||||
|
|
||||||
|
@customElement("ha-metric")
|
||||||
|
class HaMetric extends LitElement {
|
||||||
|
@property({ type: Number }) public value!: number;
|
||||||
|
|
||||||
|
@property({ type: String }) public description!: string;
|
||||||
|
|
||||||
|
@property({ type: String }) public tooltip?: string;
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
const roundedValue = roundWithOneDecimal(this.value);
|
||||||
|
return html`<ha-settings-row>
|
||||||
|
<span slot="heading"> ${this.description} </span>
|
||||||
|
<div slot="description" .title=${this.tooltip ?? ""}>
|
||||||
|
<span class="value"> ${roundedValue} % </span>
|
||||||
|
<ha-bar
|
||||||
|
class=${classMap({
|
||||||
|
"target-warning": roundedValue > 50,
|
||||||
|
"target-critical": roundedValue > 85,
|
||||||
|
})}
|
||||||
|
.value=${this.value}
|
||||||
|
></ha-bar>
|
||||||
|
</div>
|
||||||
|
</ha-settings-row>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResultGroup {
|
||||||
|
return css`
|
||||||
|
ha-settings-row {
|
||||||
|
padding: 0;
|
||||||
|
height: 54px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
ha-settings-row > div[slot="description"] {
|
||||||
|
white-space: normal;
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
ha-bar {
|
||||||
|
--ha-bar-primary-color: var(
|
||||||
|
--metric-bar-ok-color,
|
||||||
|
var(--success-color)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
.target-warning {
|
||||||
|
--ha-bar-primary-color: var(
|
||||||
|
--metric-bar-warning-color,
|
||||||
|
var(--warning-color)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
.target-critical {
|
||||||
|
--ha-bar-primary-color: var(
|
||||||
|
--metric-bar-critical-color,
|
||||||
|
var(--error-color)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
.value {
|
||||||
|
width: 48px;
|
||||||
|
padding-right: 4px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-metric": HaMetric;
|
||||||
|
}
|
||||||
|
}
|
@ -4,9 +4,9 @@ import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
|||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import type { PageNavigation } from "../layouts/hass-tabs-subpage";
|
import type { PageNavigation } from "../layouts/hass-tabs-subpage";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
|
import "./ha-clickable-list-item";
|
||||||
import "./ha-icon-next";
|
import "./ha-icon-next";
|
||||||
import "./ha-svg-icon";
|
import "./ha-svg-icon";
|
||||||
import "./ha-clickable-list-item";
|
|
||||||
|
|
||||||
@customElement("ha-navigation-list")
|
@customElement("ha-navigation-list")
|
||||||
class HaNavigationList extends LitElement {
|
class HaNavigationList extends LitElement {
|
||||||
@ -78,7 +78,7 @@ class HaNavigationList extends LitElement {
|
|||||||
.icon-background ha-svg-icon {
|
.icon-background ha-svg-icon {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
mwc-list-item {
|
ha-clickable-list-item {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: var(--navigation-list-item-title-font-size);
|
font-size: var(--navigation-list-item-title-font-size);
|
||||||
}
|
}
|
||||||
|
@ -224,7 +224,7 @@ class HaBlueprintOverview extends LitElement {
|
|||||||
.narrow=${this.narrow}
|
.narrow=${this.narrow}
|
||||||
back-path="/config"
|
back-path="/config"
|
||||||
.route=${this.route}
|
.route=${this.route}
|
||||||
.tabs=${configSections.blueprints}
|
.tabs=${configSections.automations}
|
||||||
.columns=${this._columns(this.narrow, this.hass.language)}
|
.columns=${this._columns(this.narrow, this.hass.language)}
|
||||||
.data=${this._processedBlueprints(this.blueprints)}
|
.data=${this._processedBlueprints(this.blueprints)}
|
||||||
id="entity_id"
|
id="entity_id"
|
||||||
|
@ -1,342 +0,0 @@
|
|||||||
import "@material/mwc-button/mwc-button";
|
|
||||||
import "@polymer/paper-input/paper-input";
|
|
||||||
import type { PaperInputElement } from "@polymer/paper-input/paper-input";
|
|
||||||
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
|
||||||
import { customElement, property, state } from "lit/decorators";
|
|
||||||
import memoizeOne from "memoize-one";
|
|
||||||
import { UNIT_C } from "../../../common/const";
|
|
||||||
import { createCurrencyListEl } from "../../../components/currency-datalist";
|
|
||||||
import "../../../components/ha-card";
|
|
||||||
import "../../../components/map/ha-locations-editor";
|
|
||||||
import type { MarkerLocation } from "../../../components/map/ha-locations-editor";
|
|
||||||
import { createTimezoneListEl } from "../../../components/timezone-datalist";
|
|
||||||
import { ConfigUpdateValues, saveCoreConfig } from "../../../data/core";
|
|
||||||
import { SYMBOL_TO_ISO } from "../../../data/currency";
|
|
||||||
import type { PolymerChangedEvent } from "../../../polymer-types";
|
|
||||||
import type { HomeAssistant } from "../../../types";
|
|
||||||
import "../../../components/ha-formfield";
|
|
||||||
import "../../../components/ha-radio";
|
|
||||||
import type { HaRadio } from "../../../components/ha-radio";
|
|
||||||
|
|
||||||
@customElement("ha-config-core-form")
|
|
||||||
class ConfigCoreForm extends LitElement {
|
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
|
||||||
|
|
||||||
@state() private _working = false;
|
|
||||||
|
|
||||||
@state() private _location?: [number, number];
|
|
||||||
|
|
||||||
@state() private _currency?: string;
|
|
||||||
|
|
||||||
@state() private _elevation?: string;
|
|
||||||
|
|
||||||
@state() private _unitSystem?: ConfigUpdateValues["unit_system"];
|
|
||||||
|
|
||||||
@state() private _timeZone?: string;
|
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
|
||||||
const canEdit = ["storage", "default"].includes(
|
|
||||||
this.hass.config.config_source
|
|
||||||
);
|
|
||||||
const disabled = this._working || !canEdit;
|
|
||||||
|
|
||||||
return html`
|
|
||||||
<ha-card
|
|
||||||
.header=${this.hass.localize(
|
|
||||||
"ui.panel.config.core.section.core.form.heading"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<div class="card-content">
|
|
||||||
${!canEdit
|
|
||||||
? html`
|
|
||||||
<p>
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.config.core.section.core.core_config.edit_requires_storage"
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
`
|
|
||||||
: ""}
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<ha-locations-editor
|
|
||||||
class="flex"
|
|
||||||
.hass=${this.hass}
|
|
||||||
.locations=${this._markerLocation(
|
|
||||||
this.hass.config.latitude,
|
|
||||||
this.hass.config.longitude,
|
|
||||||
this._location
|
|
||||||
)}
|
|
||||||
@location-updated=${this._locationChanged}
|
|
||||||
></ha-locations-editor>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="flex">
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.config.core.section.core.core_config.time_zone"
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<paper-input
|
|
||||||
class="flex"
|
|
||||||
.label=${this.hass.localize(
|
|
||||||
"ui.panel.config.core.section.core.core_config.time_zone"
|
|
||||||
)}
|
|
||||||
name="timeZone"
|
|
||||||
list="timezones"
|
|
||||||
.disabled=${disabled}
|
|
||||||
.value=${this._timeZoneValue}
|
|
||||||
@value-changed=${this._handleChange}
|
|
||||||
></paper-input>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="flex">
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.config.core.section.core.core_config.elevation"
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<paper-input
|
|
||||||
class="flex"
|
|
||||||
.label=${this.hass.localize(
|
|
||||||
"ui.panel.config.core.section.core.core_config.elevation"
|
|
||||||
)}
|
|
||||||
name="elevation"
|
|
||||||
type="number"
|
|
||||||
.disabled=${disabled}
|
|
||||||
.value=${this._elevationValue}
|
|
||||||
@value-changed=${this._handleChange}
|
|
||||||
>
|
|
||||||
<span slot="suffix">
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.config.core.section.core.core_config.elevation_meters"
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
</paper-input>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="flex">
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.config.core.section.core.core_config.unit_system"
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div class="radio-group">
|
|
||||||
<ha-formfield
|
|
||||||
.label=${html`${this.hass.localize(
|
|
||||||
"ui.panel.config.core.section.core.core_config.unit_system_metric"
|
|
||||||
)}
|
|
||||||
<div class="secondary">
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.config.core.section.core.core_config.metric_example"
|
|
||||||
)}
|
|
||||||
</div>`}
|
|
||||||
>
|
|
||||||
<ha-radio
|
|
||||||
name="unit_system"
|
|
||||||
value="metric"
|
|
||||||
.checked=${this._unitSystemValue === "metric"}
|
|
||||||
@change=${this._unitSystemChanged}
|
|
||||||
.disabled=${this._working}
|
|
||||||
></ha-radio>
|
|
||||||
</ha-formfield>
|
|
||||||
<ha-formfield
|
|
||||||
.label=${html`${this.hass.localize(
|
|
||||||
"ui.panel.config.core.section.core.core_config.unit_system_imperial"
|
|
||||||
)}
|
|
||||||
<div class="secondary">
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.config.core.section.core.core_config.imperial_example"
|
|
||||||
)}
|
|
||||||
</div>`}
|
|
||||||
>
|
|
||||||
<ha-radio
|
|
||||||
name="unit_system"
|
|
||||||
value="imperial"
|
|
||||||
.checked=${this._unitSystemValue === "imperial"}
|
|
||||||
@change=${this._unitSystemChanged}
|
|
||||||
.disabled=${this._working}
|
|
||||||
></ha-radio>
|
|
||||||
</ha-formfield>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="flex">
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.config.core.section.core.core_config.currency"
|
|
||||||
)}<br />
|
|
||||||
<a
|
|
||||||
href="https://en.wikipedia.org/wiki/ISO_4217#Active_codes"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>${this.hass.localize(
|
|
||||||
"ui.panel.config.core.section.core.core_config.find_currency_value"
|
|
||||||
)}</a
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<paper-input
|
|
||||||
class="flex"
|
|
||||||
.label=${this.hass.localize(
|
|
||||||
"ui.panel.config.core.section.core.core_config.currency"
|
|
||||||
)}
|
|
||||||
name="currency"
|
|
||||||
list="currencies"
|
|
||||||
.disabled=${disabled}
|
|
||||||
.value=${this._currencyValue}
|
|
||||||
@value-changed=${this._handleChange}
|
|
||||||
></paper-input>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card-actions">
|
|
||||||
<mwc-button @click=${this._save} .disabled=${disabled}>
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.config.core.section.core.core_config.save_button"
|
|
||||||
)}
|
|
||||||
</mwc-button>
|
|
||||||
</div>
|
|
||||||
</ha-card>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected firstUpdated(changedProps) {
|
|
||||||
super.firstUpdated(changedProps);
|
|
||||||
|
|
||||||
const tzInput = this.shadowRoot!.querySelector(
|
|
||||||
"[name=timeZone]"
|
|
||||||
) as PaperInputElement;
|
|
||||||
tzInput.inputElement.appendChild(createTimezoneListEl());
|
|
||||||
|
|
||||||
const cInput = this.shadowRoot!.querySelector(
|
|
||||||
"[name=currency]"
|
|
||||||
) as PaperInputElement;
|
|
||||||
cInput.inputElement.appendChild(createCurrencyListEl());
|
|
||||||
}
|
|
||||||
|
|
||||||
private _markerLocation = memoizeOne(
|
|
||||||
(
|
|
||||||
lat: number,
|
|
||||||
lng: number,
|
|
||||||
location?: [number, number]
|
|
||||||
): MarkerLocation[] => [
|
|
||||||
{
|
|
||||||
id: "location",
|
|
||||||
latitude: location ? location[0] : lat,
|
|
||||||
longitude: location ? location[1] : lng,
|
|
||||||
location_editable: true,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
private get _currencyValue() {
|
|
||||||
return this._currency !== undefined
|
|
||||||
? this._currency
|
|
||||||
: this.hass.config.currency;
|
|
||||||
}
|
|
||||||
|
|
||||||
private get _elevationValue() {
|
|
||||||
return this._elevation !== undefined
|
|
||||||
? this._elevation
|
|
||||||
: this.hass.config.elevation;
|
|
||||||
}
|
|
||||||
|
|
||||||
private get _timeZoneValue() {
|
|
||||||
return this._timeZone !== undefined
|
|
||||||
? this._timeZone
|
|
||||||
: this.hass.config.time_zone;
|
|
||||||
}
|
|
||||||
|
|
||||||
private get _unitSystemValue() {
|
|
||||||
return this._unitSystem !== undefined
|
|
||||||
? this._unitSystem
|
|
||||||
: this.hass.config.unit_system.temperature === UNIT_C
|
|
||||||
? "metric"
|
|
||||||
: "imperial";
|
|
||||||
}
|
|
||||||
|
|
||||||
private _handleChange(ev: PolymerChangedEvent<string>) {
|
|
||||||
const target = ev.currentTarget as PaperInputElement;
|
|
||||||
let value = target.value;
|
|
||||||
|
|
||||||
if (target.name === "currency" && value) {
|
|
||||||
if (value in SYMBOL_TO_ISO) {
|
|
||||||
value = SYMBOL_TO_ISO[value];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this[`_${target.name}`] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _locationChanged(ev) {
|
|
||||||
this._location = ev.detail.location;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _unitSystemChanged(ev: CustomEvent) {
|
|
||||||
this._unitSystem = (ev.target as HaRadio).value as "metric" | "imperial";
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _save() {
|
|
||||||
this._working = true;
|
|
||||||
try {
|
|
||||||
const location = this._location || [
|
|
||||||
this.hass.config.latitude,
|
|
||||||
this.hass.config.longitude,
|
|
||||||
];
|
|
||||||
await saveCoreConfig(this.hass, {
|
|
||||||
latitude: location[0],
|
|
||||||
longitude: location[1],
|
|
||||||
currency: this._currencyValue,
|
|
||||||
elevation: Number(this._elevationValue),
|
|
||||||
unit_system: this._unitSystemValue,
|
|
||||||
time_zone: this._timeZoneValue,
|
|
||||||
});
|
|
||||||
} catch (err: any) {
|
|
||||||
alert(`Error saving config: ${err.message}`);
|
|
||||||
} finally {
|
|
||||||
this._working = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
|
||||||
return css`
|
|
||||||
.row {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
margin: 0 -8px;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.secondary {
|
|
||||||
color: var(--secondary-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.flex {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.row > * {
|
|
||||||
margin: 0 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.radio-group {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-actions {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: var(--primary-color);
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface HTMLElementTagNameMap {
|
|
||||||
"ha-config-core-form": ConfigCoreForm;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
import "@polymer/app-layout/app-header/app-header";
|
|
||||||
import "@polymer/app-layout/app-toolbar/app-toolbar";
|
|
||||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
|
||||||
/* eslint-plugin-disable lit */
|
|
||||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
|
||||||
import "../../../layouts/hass-subpage";
|
|
||||||
import LocalizeMixin from "../../../mixins/localize-mixin";
|
|
||||||
import "../../../styles/polymer-ha-style";
|
|
||||||
import "./ha-config-core-form";
|
|
||||||
import "./ha-config-name-form";
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @appliesMixin LocalizeMixin
|
|
||||||
*/
|
|
||||||
class HaConfigCore extends LocalizeMixin(PolymerElement) {
|
|
||||||
static get template() {
|
|
||||||
return html`
|
|
||||||
<style include="iron-flex ha-style">
|
|
||||||
.content {
|
|
||||||
padding: 28px 20px 0;
|
|
||||||
max-width: 1040px;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
ha-config-name-form,
|
|
||||||
ha-config-core-form {
|
|
||||||
display: block;
|
|
||||||
margin-top: 24px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<hass-subpage
|
|
||||||
hass="[[hass]]"
|
|
||||||
narrow="[[narrow]]"
|
|
||||||
header="[[localize('ui.panel.config.core.caption')]]"
|
|
||||||
back-path="/config/system"
|
|
||||||
>
|
|
||||||
<div class="content">
|
|
||||||
<ha-config-name-form hass="[[hass]]"></ha-config-name-form>
|
|
||||||
<ha-config-core-form hass="[[hass]]"></ha-config-core-form>
|
|
||||||
</div>
|
|
||||||
</hass-subpage>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
static get properties() {
|
|
||||||
return {
|
|
||||||
hass: Object,
|
|
||||||
isWide: Boolean,
|
|
||||||
narrow: Boolean,
|
|
||||||
showAdvanced: Boolean,
|
|
||||||
route: Object,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
customElements.define("ha-config-core", HaConfigCore);
|
|
@ -1,97 +0,0 @@
|
|||||||
import "@material/mwc-button/mwc-button";
|
|
||||||
import { css, html, LitElement, TemplateResult } from "lit";
|
|
||||||
import { customElement, property, state } from "lit/decorators";
|
|
||||||
import "../../../components/ha-card";
|
|
||||||
import { ConfigUpdateValues, saveCoreConfig } from "../../../data/core";
|
|
||||||
import type { HomeAssistant } from "../../../types";
|
|
||||||
import "../../../components/ha-textfield";
|
|
||||||
import type { HaTextField } from "../../../components/ha-textfield";
|
|
||||||
|
|
||||||
@customElement("ha-config-name-form")
|
|
||||||
class ConfigNameForm extends LitElement {
|
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
|
||||||
|
|
||||||
@state() private _working = false;
|
|
||||||
|
|
||||||
@state() private _name!: ConfigUpdateValues["location_name"];
|
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
|
||||||
const canEdit = ["storage", "default"].includes(
|
|
||||||
this.hass.config.config_source
|
|
||||||
);
|
|
||||||
const disabled = this._working || !canEdit;
|
|
||||||
|
|
||||||
return html`
|
|
||||||
<ha-card>
|
|
||||||
<div class="card-content">
|
|
||||||
${!canEdit
|
|
||||||
? html`
|
|
||||||
<p>
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.config.core.section.core.core_config.edit_requires_storage"
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
`
|
|
||||||
: ""}
|
|
||||||
<ha-textfield
|
|
||||||
class="flex"
|
|
||||||
.label=${this.hass.localize(
|
|
||||||
"ui.panel.config.core.section.core.core_config.location_name"
|
|
||||||
)}
|
|
||||||
.disabled=${disabled}
|
|
||||||
.value=${this._nameValue}
|
|
||||||
@change=${this._handleChange}
|
|
||||||
></ha-textfield>
|
|
||||||
</div>
|
|
||||||
<div class="card-actions">
|
|
||||||
<mwc-button @click=${this._save} .disabled=${disabled}>
|
|
||||||
${this.hass.localize(
|
|
||||||
"ui.panel.config.core.section.core.core_config.save_button"
|
|
||||||
)}
|
|
||||||
</mwc-button>
|
|
||||||
</div>
|
|
||||||
</ha-card>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
private get _nameValue() {
|
|
||||||
return this._name !== undefined
|
|
||||||
? this._name
|
|
||||||
: this.hass.config.location_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _handleChange(ev) {
|
|
||||||
const target = ev.currentTarget as HaTextField;
|
|
||||||
this._name = target.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _save() {
|
|
||||||
this._working = true;
|
|
||||||
try {
|
|
||||||
await saveCoreConfig(this.hass, {
|
|
||||||
location_name: this._nameValue,
|
|
||||||
});
|
|
||||||
} catch (err: any) {
|
|
||||||
alert("FAIL");
|
|
||||||
} finally {
|
|
||||||
this._working = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static get styles() {
|
|
||||||
return css`
|
|
||||||
.card-actions {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
ha-textfield {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface HTMLElementTagNameMap {
|
|
||||||
"ha-config-name-form": ConfigNameForm;
|
|
||||||
}
|
|
||||||
}
|
|
@ -40,7 +40,7 @@ class ConfigNetwork extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<ha-card outlined header="Network">
|
<ha-card outlined header="Network Adapter">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
${this._error
|
${this._error
|
||||||
? html`
|
? html`
|
||||||
|
@ -1,7 +1,17 @@
|
|||||||
import { css, html, LitElement, TemplateResult } from "lit";
|
import { css, html, LitElement, PropertyValues, TemplateResult } from "lit";
|
||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
|
import memoizeOne from "memoize-one";
|
||||||
|
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
|
||||||
|
import "../../../components/ha-alert";
|
||||||
|
import "../../../components/ha-bar";
|
||||||
|
import "../../../components/ha-metric";
|
||||||
|
import { fetchHassioHostInfo, HassioHostInfo } from "../../../data/hassio/host";
|
||||||
import "../../../layouts/hass-subpage";
|
import "../../../layouts/hass-subpage";
|
||||||
import type { HomeAssistant, Route } from "../../../types";
|
import type { HomeAssistant, Route } from "../../../types";
|
||||||
|
import {
|
||||||
|
getValueInPercentage,
|
||||||
|
roundWithOneDecimal,
|
||||||
|
} from "../../../util/calculate";
|
||||||
import "./ha-config-analytics";
|
import "./ha-config-analytics";
|
||||||
|
|
||||||
@customElement("ha-config-section-storage")
|
@customElement("ha-config-section-storage")
|
||||||
@ -12,6 +22,17 @@ class HaConfigSectionStorage extends LitElement {
|
|||||||
|
|
||||||
@property({ type: Boolean }) public narrow!: boolean;
|
@property({ type: Boolean }) public narrow!: boolean;
|
||||||
|
|
||||||
|
@state() private _error?: { code: string; message: string };
|
||||||
|
|
||||||
|
@state() private _storageData?: HassioHostInfo;
|
||||||
|
|
||||||
|
protected firstUpdated(changedProps: PropertyValues) {
|
||||||
|
super.firstUpdated(changedProps);
|
||||||
|
if (isComponentLoaded(this.hass, "hassio")) {
|
||||||
|
this._load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
<hass-subpage
|
<hass-subpage
|
||||||
@ -19,17 +40,84 @@ class HaConfigSectionStorage extends LitElement {
|
|||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.narrow=${this.narrow}
|
.narrow=${this.narrow}
|
||||||
>
|
>
|
||||||
<div class="content"></div>
|
<div class="content">
|
||||||
|
${this._error
|
||||||
|
? html`
|
||||||
|
<ha-alert alert-type="error"
|
||||||
|
>${this._error.message || this._error.code}</ha-alert
|
||||||
|
>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
${this._storageData
|
||||||
|
? html`
|
||||||
|
<ha-card outlined>
|
||||||
|
<ha-metric
|
||||||
|
.description=${this.hass.localize(
|
||||||
|
"ui.panel.config.storage.used_space"
|
||||||
|
)}
|
||||||
|
.value=${this._getUsedSpace(
|
||||||
|
this._storageData?.disk_used,
|
||||||
|
this._storageData?.disk_total
|
||||||
|
)}
|
||||||
|
.tooltip=${`${this._storageData.disk_used} GB/${this._storageData.disk_total} GB`}
|
||||||
|
></ha-metric>
|
||||||
|
${this._storageData.disk_life_time !== "" &&
|
||||||
|
this._storageData.disk_life_time >= 10
|
||||||
|
? html`
|
||||||
|
<ha-metric
|
||||||
|
.description=${this.hass.localize(
|
||||||
|
"ui.panel.config.storage.emmc_lifetime_used"
|
||||||
|
)}
|
||||||
|
.value=${this._storageData.disk_life_time}
|
||||||
|
.tooltip=${`${
|
||||||
|
this._storageData.disk_life_time - 10
|
||||||
|
} % -
|
||||||
|
${this._storageData.disk_life_time} %`}
|
||||||
|
class="emmc"
|
||||||
|
></ha-metric>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
</ha-card>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
</div>
|
||||||
</hass-subpage>
|
</hass-subpage>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async _load() {
|
||||||
|
this._error = undefined;
|
||||||
|
try {
|
||||||
|
if (isComponentLoaded(this.hass, "hassio")) {
|
||||||
|
this._storageData = await fetchHassioHostInfo(this.hass);
|
||||||
|
}
|
||||||
|
} catch (err: any) {
|
||||||
|
this._error = err.message || err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _getUsedSpace = memoizeOne((used: number, total: number) =>
|
||||||
|
roundWithOneDecimal(getValueInPercentage(used, 0, total))
|
||||||
|
);
|
||||||
|
|
||||||
static styles = css`
|
static styles = css`
|
||||||
.content {
|
.content {
|
||||||
padding: 28px 20px 0;
|
padding: 28px 20px 0;
|
||||||
max-width: 1040px;
|
max-width: 1040px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
ha-card {
|
||||||
|
padding: 16px;
|
||||||
|
max-width: 500px;
|
||||||
|
margin: 0 auto;
|
||||||
|
height: 100%;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-direction: column;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.emmc {
|
||||||
|
--metric-bar-ok-color: #000;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
137
src/panels/config/core/ha-config-section-updates.ts
Normal file
137
src/panels/config/core/ha-config-section-updates.ts
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
import { HassEntities } from "home-assistant-js-websocket";
|
||||||
|
import { css, html, LitElement, PropertyValues, TemplateResult } from "lit";
|
||||||
|
import { customElement, property } from "lit/decorators";
|
||||||
|
import memoizeOne from "memoize-one";
|
||||||
|
import { computeStateDomain } from "../../../common/entity/compute_state_domain";
|
||||||
|
import { caseInsensitiveStringCompare } from "../../../common/string/compare";
|
||||||
|
import "../../../components/ha-alert";
|
||||||
|
import "../../../components/ha-bar";
|
||||||
|
import "../../../components/ha-metric";
|
||||||
|
import { updateCanInstall, UpdateEntity } from "../../../data/update";
|
||||||
|
import "../../../layouts/hass-subpage";
|
||||||
|
import type { HomeAssistant } from "../../../types";
|
||||||
|
import { showToast } from "../../../util/toast";
|
||||||
|
import "../dashboard/ha-config-updates";
|
||||||
|
import "./ha-config-analytics";
|
||||||
|
|
||||||
|
@customElement("ha-config-section-updates")
|
||||||
|
class HaConfigSectionUpdates extends LitElement {
|
||||||
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@property({ type: Boolean }) public narrow!: boolean;
|
||||||
|
|
||||||
|
private _notifyUpdates = false;
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
const canInstallUpdates = this._filterUpdateEntitiesWithInstall(
|
||||||
|
this.hass.states
|
||||||
|
);
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<hass-subpage
|
||||||
|
back-path="/config/system"
|
||||||
|
.hass=${this.hass}
|
||||||
|
.narrow=${this.narrow}
|
||||||
|
.header=${this.hass.localize("ui.panel.config.updates.caption")}
|
||||||
|
>
|
||||||
|
<div class="content">
|
||||||
|
<ha-card outlined>
|
||||||
|
${canInstallUpdates.length
|
||||||
|
? html`
|
||||||
|
<ha-config-updates
|
||||||
|
.hass=${this.hass}
|
||||||
|
.narrow=${this.narrow}
|
||||||
|
.updateEntities=${canInstallUpdates}
|
||||||
|
showAll
|
||||||
|
></ha-config-updates>
|
||||||
|
`
|
||||||
|
: html`
|
||||||
|
${this.hass.localize("ui.panel.config.updates.no_updates")}
|
||||||
|
`}
|
||||||
|
</ha-card>
|
||||||
|
</div>
|
||||||
|
</hass-subpage>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override updated(changedProps: PropertyValues): void {
|
||||||
|
super.updated(changedProps);
|
||||||
|
|
||||||
|
if (!changedProps.has("hass") || !this._notifyUpdates) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._notifyUpdates = false;
|
||||||
|
if (this._filterUpdateEntitiesWithInstall(this.hass.states).length) {
|
||||||
|
showToast(this, {
|
||||||
|
message: this.hass.localize(
|
||||||
|
"ui.panel.config.updates.updates_refreshed"
|
||||||
|
),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
showToast(this, {
|
||||||
|
message: this.hass.localize("ui.panel.config.updates.no_new_updates"),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _filterUpdateEntities = memoizeOne((entities: HassEntities) =>
|
||||||
|
(
|
||||||
|
Object.values(entities).filter(
|
||||||
|
(entity) => computeStateDomain(entity) === "update"
|
||||||
|
) as UpdateEntity[]
|
||||||
|
).sort((a, b) => {
|
||||||
|
if (a.attributes.title === "Home Assistant Core") {
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
if (b.attributes.title === "Home Assistant Core") {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
if (a.attributes.title === "Home Assistant Operating System") {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
if (b.attributes.title === "Home Assistant Operating System") {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
if (a.attributes.title === "Home Assistant Supervisor") {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (b.attributes.title === "Home Assistant Supervisor") {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return caseInsensitiveStringCompare(
|
||||||
|
a.attributes.title || a.attributes.friendly_name || "",
|
||||||
|
b.attributes.title || b.attributes.friendly_name || ""
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
private _filterUpdateEntitiesWithInstall = memoizeOne(
|
||||||
|
(entities: HassEntities) =>
|
||||||
|
this._filterUpdateEntities(entities).filter((entity) =>
|
||||||
|
updateCanInstall(entity)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
static styles = css`
|
||||||
|
.content {
|
||||||
|
padding: 28px 20px 0;
|
||||||
|
max-width: 1040px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
ha-card {
|
||||||
|
padding: 16px;
|
||||||
|
max-width: 500px;
|
||||||
|
margin: 0 auto;
|
||||||
|
height: 100%;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-direction: column;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-config-section-updates": HaConfigSectionUpdates;
|
||||||
|
}
|
||||||
|
}
|
@ -33,7 +33,7 @@ class HaConfigSystemNavigation extends LitElement {
|
|||||||
return html`
|
return html`
|
||||||
<hass-subpage
|
<hass-subpage
|
||||||
back-path="/config"
|
back-path="/config"
|
||||||
.header=${this.hass.localize("ui.panel.config.dashboard.system.title")}
|
.header=${this.hass.localize("ui.panel.config.dashboard.system.main")}
|
||||||
>
|
>
|
||||||
<ha-config-section
|
<ha-config-section
|
||||||
.narrow=${this.narrow}
|
.narrow=${this.narrow}
|
||||||
@ -43,9 +43,7 @@ class HaConfigSystemNavigation extends LitElement {
|
|||||||
<ha-card>
|
<ha-card>
|
||||||
${this.narrow
|
${this.narrow
|
||||||
? html`<div class="title">
|
? html`<div class="title">
|
||||||
${this.hass.localize(
|
${this.hass.localize("ui.panel.config.dashboard.system.main")}
|
||||||
"ui.panel.config.dashboard.system.title"
|
|
||||||
)}
|
|
||||||
</div>`
|
</div>`
|
||||||
: ""}
|
: ""}
|
||||||
<ha-navigation-list
|
<ha-navigation-list
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import "@material/mwc-list/mwc-list";
|
import "@material/mwc-list/mwc-list";
|
||||||
import "@material/mwc-list/mwc-list-item";
|
import "@material/mwc-list/mwc-list-item";
|
||||||
import { html, LitElement, TemplateResult } from "lit";
|
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import { canShowPage } from "../../../common/config/can_show_page";
|
import { canShowPage } from "../../../common/config/can_show_page";
|
||||||
import "../../../components/ha-card";
|
import "../../../components/ha-card";
|
||||||
@ -30,7 +30,7 @@ class HaConfigNavigation extends LitElement {
|
|||||||
name:
|
name:
|
||||||
page.name ||
|
page.name ||
|
||||||
this.hass.localize(
|
this.hass.localize(
|
||||||
`ui.panel.config.dashboard.${page.translationKey}.title`
|
`ui.panel.config.dashboard.${page.translationKey}.main`
|
||||||
),
|
),
|
||||||
description:
|
description:
|
||||||
page.component === "cloud" && (page.info as CloudStatus)
|
page.component === "cloud" && (page.info as CloudStatus)
|
||||||
@ -51,7 +51,7 @@ class HaConfigNavigation extends LitElement {
|
|||||||
${
|
${
|
||||||
page.description ||
|
page.description ||
|
||||||
this.hass.localize(
|
this.hass.localize(
|
||||||
`ui.panel.config.dashboard.${page.translationKey}.description`
|
`ui.panel.config.dashboard.${page.translationKey}.secondary`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
@ -81,6 +81,12 @@ class HaConfigNavigation extends LitElement {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static styles: CSSResultGroup = css`
|
||||||
|
ha-navigation-list {
|
||||||
|
--navigation-list-item-title-font-size: 16px;
|
||||||
|
}
|
||||||
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -2,7 +2,7 @@ import "@material/mwc-button/mwc-button";
|
|||||||
import "@polymer/paper-item/paper-icon-item";
|
import "@polymer/paper-item/paper-icon-item";
|
||||||
import "@polymer/paper-item/paper-item-body";
|
import "@polymer/paper-item/paper-item-body";
|
||||||
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
import "../../../components/entity/state-badge";
|
import "../../../components/entity/state-badge";
|
||||||
import "../../../components/ha-alert";
|
import "../../../components/ha-alert";
|
||||||
@ -19,7 +19,7 @@ class HaConfigUpdates extends LitElement {
|
|||||||
@property({ attribute: false })
|
@property({ attribute: false })
|
||||||
public updateEntities?: UpdateEntity[];
|
public updateEntities?: UpdateEntity[];
|
||||||
|
|
||||||
@state() private _showAll = false;
|
@property({ type: Boolean, reflect: true }) showAll = false;
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
if (!this.updateEntities?.length) {
|
if (!this.updateEntities?.length) {
|
||||||
@ -27,7 +27,7 @@ class HaConfigUpdates extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const updates =
|
const updates =
|
||||||
this._showAll || this.updateEntities.length <= 3
|
this.showAll || this.updateEntities.length <= 3
|
||||||
? this.updateEntities
|
? this.updateEntities
|
||||||
: this.updateEntities.slice(0, 2);
|
: this.updateEntities.slice(0, 2);
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ class HaConfigUpdates extends LitElement {
|
|||||||
</paper-icon-item>
|
</paper-icon-item>
|
||||||
`
|
`
|
||||||
)}
|
)}
|
||||||
${!this._showAll && this.updateEntities.length >= 4
|
${!this.showAll && this.updateEntities.length >= 4
|
||||||
? html`
|
? html`
|
||||||
<button class="show-more" @click=${this._showAllClicked}>
|
<button class="show-more" @click=${this._showAllClicked}>
|
||||||
${this.hass.localize("ui.panel.config.updates.more_updates", {
|
${this.hass.localize("ui.panel.config.updates.more_updates", {
|
||||||
@ -85,7 +85,7 @@ class HaConfigUpdates extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _showAllClicked() {
|
private _showAllClicked() {
|
||||||
this._showAll = true;
|
this.showAll = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultGroup[] {
|
static get styles(): CSSResultGroup[] {
|
||||||
|
@ -6,7 +6,6 @@ import {
|
|||||||
mdiCog,
|
mdiCog,
|
||||||
mdiCpu32Bit,
|
mdiCpu32Bit,
|
||||||
mdiDevices,
|
mdiDevices,
|
||||||
mdiHomeAssistant,
|
|
||||||
mdiInformation,
|
mdiInformation,
|
||||||
mdiInformationOutline,
|
mdiInformationOutline,
|
||||||
mdiLightningBolt,
|
mdiLightningBolt,
|
||||||
@ -261,14 +260,6 @@ export const configSections: { [name: string]: PageNavigation[] } = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
general: [
|
general: [
|
||||||
{
|
|
||||||
component: "core",
|
|
||||||
path: "/config/core",
|
|
||||||
translationKey: "ui.panel.config.core.caption",
|
|
||||||
iconPath: mdiHomeAssistant,
|
|
||||||
iconColor: "#4A5963",
|
|
||||||
core: true,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
component: "server_control",
|
component: "server_control",
|
||||||
path: "/config/server_control",
|
path: "/config/server_control",
|
||||||
@ -277,19 +268,25 @@ export const configSections: { [name: string]: PageNavigation[] } = {
|
|||||||
iconColor: "#4A5963",
|
iconColor: "#4A5963",
|
||||||
core: true,
|
core: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/config/updates",
|
||||||
|
translationKey: "ui.panel.config.updates.caption",
|
||||||
|
iconPath: mdiUpdate,
|
||||||
|
iconColor: "#3B808E",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
component: "logs",
|
component: "logs",
|
||||||
path: "/config/logs",
|
path: "/config/logs",
|
||||||
translationKey: "ui.panel.config.logs.caption",
|
translationKey: "ui.panel.config.logs.caption",
|
||||||
iconPath: mdiMathLog,
|
iconPath: mdiMathLog,
|
||||||
iconColor: "#4A5963",
|
iconColor: "#C65326",
|
||||||
core: true,
|
core: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/config/backup",
|
path: "/config/backup",
|
||||||
translationKey: "ui.panel.config.backup.caption",
|
translationKey: "ui.panel.config.backup.caption",
|
||||||
iconPath: mdiBackupRestore,
|
iconPath: mdiBackupRestore,
|
||||||
iconColor: "#4084CD",
|
iconColor: "#0D47A1",
|
||||||
component: "backup",
|
component: "backup",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -298,12 +295,6 @@ export const configSections: { [name: string]: PageNavigation[] } = {
|
|||||||
iconPath: mdiShape,
|
iconPath: mdiShape,
|
||||||
iconColor: "#f1c447",
|
iconColor: "#f1c447",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: "/config/hardware",
|
|
||||||
translationKey: "ui.panel.config.hardware.caption",
|
|
||||||
iconPath: mdiCpu32Bit,
|
|
||||||
iconColor: "#4A5963",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: "/config/network",
|
path: "/config/network",
|
||||||
translationKey: "ui.panel.config.network.caption",
|
translationKey: "ui.panel.config.network.caption",
|
||||||
@ -317,10 +308,10 @@ export const configSections: { [name: string]: PageNavigation[] } = {
|
|||||||
iconColor: "#518C43",
|
iconColor: "#518C43",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/config/update",
|
path: "/config/hardware",
|
||||||
translationKey: "ui.panel.config.updates.caption",
|
translationKey: "ui.panel.config.hardware.caption",
|
||||||
iconPath: mdiUpdate,
|
iconPath: mdiCpu32Bit,
|
||||||
iconColor: "#4A5963",
|
iconColor: "#301A8E",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
about: [
|
about: [
|
||||||
@ -374,10 +365,6 @@ class HaPanelConfig extends HassRouterPage {
|
|||||||
tag: "ha-config-cloud",
|
tag: "ha-config-cloud",
|
||||||
load: () => import("./cloud/ha-config-cloud"),
|
load: () => import("./cloud/ha-config-cloud"),
|
||||||
},
|
},
|
||||||
core: {
|
|
||||||
tag: "ha-config-core",
|
|
||||||
load: () => import("./core/ha-config-core"),
|
|
||||||
},
|
|
||||||
devices: {
|
devices: {
|
||||||
tag: "ha-config-devices",
|
tag: "ha-config-devices",
|
||||||
load: () => import("./devices/ha-config-devices"),
|
load: () => import("./devices/ha-config-devices"),
|
||||||
@ -444,6 +431,10 @@ class HaPanelConfig extends HassRouterPage {
|
|||||||
tag: "ha-config-section-storage",
|
tag: "ha-config-section-storage",
|
||||||
load: () => import("./core/ha-config-section-storage"),
|
load: () => import("./core/ha-config-section-storage"),
|
||||||
},
|
},
|
||||||
|
updates: {
|
||||||
|
tag: "ha-config-section-updates",
|
||||||
|
load: () => import("./core/ha-config-section-updates"),
|
||||||
|
},
|
||||||
users: {
|
users: {
|
||||||
tag: "ha-config-users",
|
tag: "ha-config-users",
|
||||||
load: () => import("./users/ha-config-users"),
|
load: () => import("./users/ha-config-users"),
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
mdiCheck,
|
mdiCheck,
|
||||||
mdiCheckCircleOutline,
|
mdiCheckCircleOutline,
|
||||||
|
mdiDotsVertical,
|
||||||
mdiOpenInNew,
|
mdiOpenInNew,
|
||||||
mdiPlus,
|
mdiPlus,
|
||||||
} from "@mdi/js";
|
} from "@mdi/js";
|
||||||
@ -16,6 +17,7 @@ import {
|
|||||||
DataTableColumnContainer,
|
DataTableColumnContainer,
|
||||||
RowClickedEvent,
|
RowClickedEvent,
|
||||||
} from "../../../../components/data-table/ha-data-table";
|
} from "../../../../components/data-table/ha-data-table";
|
||||||
|
import "../../../../components/ha-clickable-list-item";
|
||||||
import "../../../../components/ha-fab";
|
import "../../../../components/ha-fab";
|
||||||
import "../../../../components/ha-icon";
|
import "../../../../components/ha-icon";
|
||||||
import "../../../../components/ha-icon-button";
|
import "../../../../components/ha-icon-button";
|
||||||
@ -216,7 +218,7 @@ export class HaConfigLovelaceDashboards extends LitElement {
|
|||||||
if (isComponentLoaded(this.hass, "energy")) {
|
if (isComponentLoaded(this.hass, "energy")) {
|
||||||
result.push({
|
result.push({
|
||||||
icon: "hass:lightning-bolt",
|
icon: "hass:lightning-bolt",
|
||||||
title: this.hass.localize(`ui.panel.config.dashboard.energy.title`),
|
title: this.hass.localize(`ui.panel.config.dashboard.energy.main`),
|
||||||
show_in_sidebar: true,
|
show_in_sidebar: true,
|
||||||
mode: "storage",
|
mode: "storage",
|
||||||
url_path: "energy",
|
url_path: "energy",
|
||||||
@ -260,6 +262,32 @@ export class HaConfigLovelaceDashboards extends LitElement {
|
|||||||
hasFab
|
hasFab
|
||||||
clickable
|
clickable
|
||||||
>
|
>
|
||||||
|
${this.hass.userData?.showAdvanced
|
||||||
|
? html`
|
||||||
|
<ha-button-menu
|
||||||
|
corner="BOTTOM_START"
|
||||||
|
slot="toolbar-icon"
|
||||||
|
activatable
|
||||||
|
>
|
||||||
|
<ha-icon-button
|
||||||
|
slot="trigger"
|
||||||
|
.label=${this.hass.localize("ui.common.menu")}
|
||||||
|
.path=${mdiDotsVertical}
|
||||||
|
></ha-icon-button>
|
||||||
|
<ha-clickable-list-item
|
||||||
|
@click=${this._entryClicked}
|
||||||
|
href="/config/lovelace/resources"
|
||||||
|
aria-label=${this.hass.localize(
|
||||||
|
"ui.panel.config.lovelace.resources.caption"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.lovelace.resources.caption"
|
||||||
|
)}
|
||||||
|
</ha-clickable-list-item>
|
||||||
|
</ha-button-menu>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
<ha-fab
|
<ha-fab
|
||||||
slot="fab"
|
slot="fab"
|
||||||
.label=${this.hass.localize(
|
.label=${this.hass.localize(
|
||||||
@ -354,4 +382,8 @@ export class HaConfigLovelaceDashboards extends LitElement {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _entryClicked(ev) {
|
||||||
|
ev.currentTarget.blur();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,13 +12,6 @@ export const lovelaceTabs = [
|
|||||||
translationKey: "ui.panel.config.lovelace.dashboards.caption",
|
translationKey: "ui.panel.config.lovelace.dashboards.caption",
|
||||||
icon: "hass:view-dashboard",
|
icon: "hass:view-dashboard",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
component: "lovelace",
|
|
||||||
path: "/config/lovelace/resources",
|
|
||||||
translationKey: "ui.panel.config.lovelace.resources.caption",
|
|
||||||
icon: "hass:file-multiple",
|
|
||||||
advancedOnly: true,
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("ha-config-lovelace")
|
@customElement("ha-config-lovelace")
|
||||||
|
@ -157,7 +157,7 @@ export class HaConfigUsers extends LitElement {
|
|||||||
.narrow=${this.narrow}
|
.narrow=${this.narrow}
|
||||||
.route=${this.route}
|
.route=${this.route}
|
||||||
backPath="/config"
|
backPath="/config"
|
||||||
.tabs=${configSections.areas}
|
.tabs=${configSections.persons}
|
||||||
.columns=${this._columns(this.narrow, this.hass.localize)}
|
.columns=${this._columns(this.narrow, this.hass.localize)}
|
||||||
.data=${this._users}
|
.data=${this._users}
|
||||||
@row-click=${this._editUser}
|
@row-click=${this._editUser}
|
||||||
|
278
src/panels/config/zone/dialog-core-zone-detail.ts
Normal file
278
src/panels/config/zone/dialog-core-zone-detail.ts
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
import "@material/mwc-button";
|
||||||
|
import "@material/mwc-list/mwc-list";
|
||||||
|
import "@material/mwc-list/mwc-list-item";
|
||||||
|
import timezones from "google-timezones-json";
|
||||||
|
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
||||||
|
import { customElement, property, state } from "lit/decorators";
|
||||||
|
import { UNIT_C } from "../../../common/const";
|
||||||
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
|
import { stopPropagation } from "../../../common/dom/stop_propagation";
|
||||||
|
import { currencies } from "../../../components/currency-datalist";
|
||||||
|
import { createCloseHeading } from "../../../components/ha-dialog";
|
||||||
|
import { HaRadio } from "../../../components/ha-radio";
|
||||||
|
import "../../../components/ha-select";
|
||||||
|
import { ConfigUpdateValues, saveCoreConfig } from "../../../data/core";
|
||||||
|
import { SYMBOL_TO_ISO } from "../../../data/currency";
|
||||||
|
import { haStyleDialog } from "../../../resources/styles";
|
||||||
|
import type { HomeAssistant } from "../../../types";
|
||||||
|
|
||||||
|
@customElement("dialog-core-zone-detail")
|
||||||
|
class DialogZoneDetail extends LitElement {
|
||||||
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@state() private _submitting = false;
|
||||||
|
|
||||||
|
@state() private _open = false;
|
||||||
|
|
||||||
|
@state() private _unitSystem?: ConfigUpdateValues["unit_system"];
|
||||||
|
|
||||||
|
@state() private _currency?: string;
|
||||||
|
|
||||||
|
@state() private _name?: string;
|
||||||
|
|
||||||
|
@state() private _elevation?: number;
|
||||||
|
|
||||||
|
@state() private _timeZone?: string;
|
||||||
|
|
||||||
|
public showDialog(): void {
|
||||||
|
this._submitting = false;
|
||||||
|
this._unitSystem =
|
||||||
|
this.hass.config.unit_system.temperature === UNIT_C
|
||||||
|
? "metric"
|
||||||
|
: "imperial";
|
||||||
|
this._currency = this.hass.config.currency;
|
||||||
|
this._elevation = this.hass.config.elevation;
|
||||||
|
this._timeZone = this.hass.config.time_zone;
|
||||||
|
this._name = this.hass.config.location_name;
|
||||||
|
this._open = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public closeDialog(): void {
|
||||||
|
this._open = false;
|
||||||
|
this._currency = undefined;
|
||||||
|
this._elevation = undefined;
|
||||||
|
this._timeZone = undefined;
|
||||||
|
this._unitSystem = undefined;
|
||||||
|
this._name = undefined;
|
||||||
|
|
||||||
|
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
const canEdit = ["storage", "default"].includes(
|
||||||
|
this.hass.config.config_source
|
||||||
|
);
|
||||||
|
const disabled = this._submitting || !canEdit;
|
||||||
|
|
||||||
|
if (!this._open) {
|
||||||
|
return html``;
|
||||||
|
}
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<ha-dialog
|
||||||
|
open
|
||||||
|
@closed=${this.closeDialog}
|
||||||
|
scrimClickAction
|
||||||
|
escapeKeyAction
|
||||||
|
.heading=${createCloseHeading(this.hass, "Core Zone Configuration")}
|
||||||
|
>
|
||||||
|
${!canEdit
|
||||||
|
? html`
|
||||||
|
<p>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.edit_requires_storage"
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
<ha-textfield
|
||||||
|
name="name"
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.location_name"
|
||||||
|
)}
|
||||||
|
.disabled=${disabled}
|
||||||
|
.value=${this._name}
|
||||||
|
@change=${this._handleChange}
|
||||||
|
></ha-textfield>
|
||||||
|
<ha-select
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.time_zone"
|
||||||
|
)}
|
||||||
|
name="timeZone"
|
||||||
|
fixedMenuPosition
|
||||||
|
naturalMenuWidth
|
||||||
|
.disabled=${disabled}
|
||||||
|
.value=${this._timeZone}
|
||||||
|
@closed=${stopPropagation}
|
||||||
|
@change=${this._handleChange}
|
||||||
|
>
|
||||||
|
${Object.keys(timezones).map(
|
||||||
|
(tz) =>
|
||||||
|
html`<mwc-list-item value=${tz}>${timezones[tz]}</mwc-list-item>`
|
||||||
|
)}
|
||||||
|
</ha-select>
|
||||||
|
<ha-textfield
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.elevation"
|
||||||
|
)}
|
||||||
|
name="elevation"
|
||||||
|
type="number"
|
||||||
|
.disabled=${disabled}
|
||||||
|
.value=${this._elevation}
|
||||||
|
@change=${this._handleChange}
|
||||||
|
>
|
||||||
|
<span slot="suffix">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.elevation_meters"
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</ha-textfield>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.unit_system"
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<ha-formfield
|
||||||
|
.label=${html`${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.unit_system_metric"
|
||||||
|
)}
|
||||||
|
<div class="secondary">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.metric_example"
|
||||||
|
)}
|
||||||
|
</div>`}
|
||||||
|
>
|
||||||
|
<ha-radio
|
||||||
|
name="unit_system"
|
||||||
|
value="metric"
|
||||||
|
.checked=${this._unitSystem === "metric"}
|
||||||
|
@change=${this._unitSystemChanged}
|
||||||
|
.disabled=${this._submitting}
|
||||||
|
></ha-radio>
|
||||||
|
</ha-formfield>
|
||||||
|
<ha-formfield
|
||||||
|
.label=${html`${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.unit_system_imperial"
|
||||||
|
)}
|
||||||
|
<div class="secondary">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.imperial_example"
|
||||||
|
)}
|
||||||
|
</div>`}
|
||||||
|
>
|
||||||
|
<ha-radio
|
||||||
|
name="unit_system"
|
||||||
|
value="imperial"
|
||||||
|
.checked=${this._unitSystem === "imperial"}
|
||||||
|
@change=${this._unitSystemChanged}
|
||||||
|
.disabled=${this._submitting}
|
||||||
|
></ha-radio>
|
||||||
|
</ha-formfield>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<ha-select
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.currency"
|
||||||
|
)}
|
||||||
|
name="currency"
|
||||||
|
fixedMenuPosition
|
||||||
|
naturalMenuWidth
|
||||||
|
.disabled=${disabled}
|
||||||
|
.value=${this._currency}
|
||||||
|
@closed=${stopPropagation}
|
||||||
|
@change=${this._handleChange}
|
||||||
|
>
|
||||||
|
${currencies.map(
|
||||||
|
(currency) =>
|
||||||
|
html`<mwc-list-item .value=${currency}
|
||||||
|
>${currency}</mwc-list-item
|
||||||
|
>`
|
||||||
|
)}</ha-select
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="https://en.wikipedia.org/wiki/ISO_4217#Active_codes"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.find_currency_value"
|
||||||
|
)}</a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<mwc-button slot="primaryAction" @click=${this._updateEntry}>
|
||||||
|
${this.hass!.localize("ui.panel.config.zone.detail.update")}
|
||||||
|
</mwc-button>
|
||||||
|
</ha-dialog>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _handleChange(ev) {
|
||||||
|
const target = ev.currentTarget;
|
||||||
|
let value = target.value;
|
||||||
|
|
||||||
|
if (target.name === "currency" && value) {
|
||||||
|
if (value in SYMBOL_TO_ISO) {
|
||||||
|
value = SYMBOL_TO_ISO[value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this[`_${target.name}`] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _unitSystemChanged(ev: CustomEvent) {
|
||||||
|
this._unitSystem = (ev.target as HaRadio).value as "metric" | "imperial";
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _updateEntry() {
|
||||||
|
this._submitting = true;
|
||||||
|
try {
|
||||||
|
await saveCoreConfig(this.hass, {
|
||||||
|
currency: this._currency,
|
||||||
|
elevation: Number(this._elevation),
|
||||||
|
unit_system: this._unitSystem,
|
||||||
|
time_zone: this._timeZone,
|
||||||
|
location_name: this._name,
|
||||||
|
});
|
||||||
|
} catch (err: any) {
|
||||||
|
alert(`Error saving config: ${err.message}`);
|
||||||
|
} finally {
|
||||||
|
this._submitting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.closeDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResultGroup {
|
||||||
|
return [
|
||||||
|
haStyleDialog,
|
||||||
|
css`
|
||||||
|
ha-dialog {
|
||||||
|
--mdc-dialog-min-width: 600px;
|
||||||
|
}
|
||||||
|
@media all and (max-width: 450px), all and (max-height: 500px) {
|
||||||
|
ha-dialog {
|
||||||
|
--mdc-dialog-min-width: calc(
|
||||||
|
100vw - env(safe-area-inset-right) - env(safe-area-inset-left)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.card-actions {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
ha-dialog > * {
|
||||||
|
display: block;
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
ha-select {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"dialog-core-zone-detail": DialogZoneDetail;
|
||||||
|
}
|
||||||
|
}
|
@ -13,7 +13,6 @@ import {
|
|||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit";
|
} from "lit";
|
||||||
import { customElement, property, query, state } from "lit/decorators";
|
import { customElement, property, query, state } from "lit/decorators";
|
||||||
import { ifDefined } from "lit/directives/if-defined";
|
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { computeStateDomain } from "../../../common/entity/compute_state_domain";
|
import { computeStateDomain } from "../../../common/entity/compute_state_domain";
|
||||||
import { navigate } from "../../../common/navigate";
|
import { navigate } from "../../../common/navigate";
|
||||||
@ -44,6 +43,7 @@ import { SubscribeMixin } from "../../../mixins/subscribe-mixin";
|
|||||||
import type { HomeAssistant, Route } from "../../../types";
|
import type { HomeAssistant, Route } from "../../../types";
|
||||||
import "../ha-config-section";
|
import "../ha-config-section";
|
||||||
import { configSections } from "../ha-panel-config";
|
import { configSections } from "../ha-panel-config";
|
||||||
|
import { showCoreZoneDetailDialog } from "./show-dialog-core-zone-detail";
|
||||||
import { showZoneDetailDialog } from "./show-dialog-zone-detail";
|
import { showZoneDetailDialog } from "./show-dialog-zone-detail";
|
||||||
|
|
||||||
@customElement("ha-config-zone")
|
@customElement("ha-config-zone")
|
||||||
@ -186,15 +186,9 @@ export class HaConfigZone extends SubscribeMixin(LitElement) {
|
|||||||
<ha-icon-button
|
<ha-icon-button
|
||||||
.entityId=${stateObject.entity_id}
|
.entityId=${stateObject.entity_id}
|
||||||
@click=${this._openCoreConfig}
|
@click=${this._openCoreConfig}
|
||||||
disabled=${ifDefined(
|
.disabled=${stateObject.entity_id === "zone.home" &&
|
||||||
stateObject.entity_id === "zone.home" &&
|
!this._canEditCore}
|
||||||
this.narrow &&
|
|
||||||
this._canEditCore
|
|
||||||
? undefined
|
|
||||||
: true
|
|
||||||
)}
|
|
||||||
.path=${stateObject.entity_id === "zone.home" &&
|
.path=${stateObject.entity_id === "zone.home" &&
|
||||||
this.narrow &&
|
|
||||||
this._canEditCore
|
this._canEditCore
|
||||||
? mdiPencil
|
? mdiPencil
|
||||||
: mdiPencilOff}
|
: mdiPencilOff}
|
||||||
@ -391,22 +385,8 @@ export class HaConfigZone extends SubscribeMixin(LitElement) {
|
|||||||
this._openDialog(entry);
|
this._openDialog(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _openCoreConfig(ev: Event) {
|
private async _openCoreConfig() {
|
||||||
const entityId: string = (ev.currentTarget! as any).entityId;
|
showCoreZoneDetailDialog(this);
|
||||||
if (entityId !== "zone.home" || !this.narrow || !this._canEditCore) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
!(await showConfirmationDialog(this, {
|
|
||||||
title: this.hass.localize("ui.panel.config.zone.go_to_core_config"),
|
|
||||||
text: this.hass.localize("ui.panel.config.zone.home_zone_core_config"),
|
|
||||||
confirmText: this.hass!.localize("ui.common.yes"),
|
|
||||||
dismissText: this.hass!.localize("ui.common.no"),
|
|
||||||
}))
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
navigate("/config/core");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _createEntry(values: ZoneMutableParams) {
|
private async _createEntry(values: ZoneMutableParams) {
|
||||||
|
12
src/panels/config/zone/show-dialog-core-zone-detail.ts
Normal file
12
src/panels/config/zone/show-dialog-core-zone-detail.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
|
|
||||||
|
export const loadCoreZoneDetailDialog = () =>
|
||||||
|
import("./dialog-core-zone-detail");
|
||||||
|
|
||||||
|
export const showCoreZoneDetailDialog = (element: HTMLElement): void => {
|
||||||
|
fireEvent(element, "show-dialog", {
|
||||||
|
dialogTag: "dialog-core-zone-detail",
|
||||||
|
dialogImport: loadCoreZoneDetailDialog,
|
||||||
|
dialogParams: {},
|
||||||
|
});
|
||||||
|
};
|
@ -1066,52 +1066,52 @@
|
|||||||
"header": "Configure Home Assistant",
|
"header": "Configure Home Assistant",
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"devices": {
|
"devices": {
|
||||||
"title": "Devices & Services",
|
"main": "Devices & Services",
|
||||||
"description": "Integrations, devices, entities and helpers"
|
"secondary": "Integrations, devices, entities and helpers"
|
||||||
},
|
},
|
||||||
"automations": {
|
"automations": {
|
||||||
"title": "Automations & Scenes",
|
"main": "Automations & Scenes",
|
||||||
"description": "Manage automations, scenes, scripts and blueprints"
|
"secondary": "Manage automations, scenes, scripts and blueprints"
|
||||||
},
|
},
|
||||||
"backup": {
|
"backup": {
|
||||||
"title": "Backup",
|
"main": "Backup",
|
||||||
"description": "Generate backups of your Home Assistant configuration"
|
"secondary": "Generate backups of your Home Assistant configuration"
|
||||||
},
|
},
|
||||||
"supervisor": {
|
"supervisor": {
|
||||||
"title": "Add-ons",
|
"main": "Add-ons",
|
||||||
"description": "Extend the function around Home Assistant"
|
"secondary": "Extend the function around Home Assistant"
|
||||||
},
|
},
|
||||||
"dashboards": {
|
"dashboards": {
|
||||||
"title": "Dashboards",
|
"main": "Dashboards",
|
||||||
"description": "Create customized sets of cards to control your home"
|
"secondary": "Create customized sets of cards to control your home"
|
||||||
},
|
},
|
||||||
"energy": {
|
"energy": {
|
||||||
"title": "Energy",
|
"main": "Energy",
|
||||||
"description": "Monitor your energy production and consumption"
|
"secondary": "Monitor your energy production and consumption"
|
||||||
},
|
},
|
||||||
"tags": {
|
"tags": {
|
||||||
"title": "Tags",
|
"main": "Tags",
|
||||||
"description": "Trigger automations when an NFC tag, QR code, etc. is scanned"
|
"secondary": "Trigger automations when an NFC tag, QR code, etc. is scanned"
|
||||||
},
|
},
|
||||||
"people": {
|
"people": {
|
||||||
"title": "People",
|
"main": "People",
|
||||||
"description": "Manage the people that Home Assistant tracks"
|
"secondary": "Manage the people that Home Assistant tracks"
|
||||||
},
|
},
|
||||||
"areas": {
|
"areas": {
|
||||||
"title": "Areas & Zones",
|
"main": "Areas & Zones",
|
||||||
"description": "Manage areas & zones that Home Assistant tracks"
|
"secondary": "Manage areas and zones that Home Assistant tracks"
|
||||||
},
|
},
|
||||||
"companion": {
|
"companion": {
|
||||||
"title": "Companion App",
|
"main": "Companion App",
|
||||||
"description": "Location and notifications"
|
"secondary": "Location and notifications"
|
||||||
},
|
},
|
||||||
"system": {
|
"system": {
|
||||||
"title": "System",
|
"main": "System",
|
||||||
"description": "Create backups, check logs or reboot your system"
|
"secondary": "Create backups, check logs or reboot your system"
|
||||||
},
|
},
|
||||||
"about": {
|
"about": {
|
||||||
"title": "About",
|
"main": "About",
|
||||||
"description": "Version, system health and links to documentation"
|
"secondary": "Version, system health and links to documentation"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
@ -1122,6 +1122,7 @@
|
|||||||
},
|
},
|
||||||
"updates": {
|
"updates": {
|
||||||
"caption": "Updates",
|
"caption": "Updates",
|
||||||
|
"no_updates": "No updates available",
|
||||||
"no_update_entities": {
|
"no_update_entities": {
|
||||||
"title": "Unable to check for updates",
|
"title": "Unable to check for updates",
|
||||||
"description": "You do not have any integrations that provide updates."
|
"description": "You do not have any integrations that provide updates."
|
||||||
@ -1778,7 +1779,7 @@
|
|||||||
"geo_location": {
|
"geo_location": {
|
||||||
"label": "Geolocation",
|
"label": "Geolocation",
|
||||||
"source": "Source",
|
"source": "Source",
|
||||||
"zone": "Location",
|
"zone": "Zone",
|
||||||
"event": "Event",
|
"event": "Event",
|
||||||
"enter": "Enter",
|
"enter": "Enter",
|
||||||
"leave": "Leave"
|
"leave": "Leave"
|
||||||
@ -3109,7 +3110,9 @@
|
|||||||
"caption": "Network"
|
"caption": "Network"
|
||||||
},
|
},
|
||||||
"storage": {
|
"storage": {
|
||||||
"caption": "Storage"
|
"caption": "Storage",
|
||||||
|
"used_space": "Used Space",
|
||||||
|
"emmc_lifetime_used": "eMMC Lifetime Used"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lovelace": {
|
"lovelace": {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user