mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-18 23:06:40 +00:00
Merge pull request #9692 from home-assistant/dev
This commit is contained in:
commit
e09ef7862e
2
setup.py
2
setup.py
@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="home-assistant-frontend",
|
name="home-assistant-frontend",
|
||||||
version="20210802.0",
|
version="20210803.0",
|
||||||
description="The Home Assistant frontend",
|
description="The Home Assistant frontend",
|
||||||
url="https://github.com/home-assistant/frontend",
|
url="https://github.com/home-assistant/frontend",
|
||||||
author="The Home Assistant Authors",
|
author="The Home Assistant Authors",
|
||||||
|
@ -8,6 +8,7 @@ import { customElement, property, state } from "lit/decorators";
|
|||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { fireEvent } from "../common/dom/fire_event";
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
import type { LocalizeFunc } from "../common/translations/localize";
|
import type { LocalizeFunc } from "../common/translations/localize";
|
||||||
|
import { createCurrencyListEl } from "../components/currency-datalist";
|
||||||
import "../components/map/ha-locations-editor";
|
import "../components/map/ha-locations-editor";
|
||||||
import type { MarkerLocation } from "../components/map/ha-locations-editor";
|
import type { MarkerLocation } from "../components/map/ha-locations-editor";
|
||||||
import { createTimezoneListEl } from "../components/timezone-datalist";
|
import { createTimezoneListEl } from "../components/timezone-datalist";
|
||||||
@ -16,11 +17,12 @@ import {
|
|||||||
detectCoreConfig,
|
detectCoreConfig,
|
||||||
saveCoreConfig,
|
saveCoreConfig,
|
||||||
} from "../data/core";
|
} from "../data/core";
|
||||||
|
import { SYMBOL_TO_ISO } from "../data/currency";
|
||||||
import { onboardCoreConfigStep } from "../data/onboarding";
|
import { onboardCoreConfigStep } from "../data/onboarding";
|
||||||
import type { PolymerChangedEvent } from "../polymer-types";
|
import type { PolymerChangedEvent } from "../polymer-types";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
|
|
||||||
const amsterdam = [52.3731339, 4.8903147];
|
const amsterdam: [number, number] = [52.3731339, 4.8903147];
|
||||||
const mql = matchMedia("(prefers-color-scheme: dark)");
|
const mql = matchMedia("(prefers-color-scheme: dark)");
|
||||||
|
|
||||||
@customElement("onboarding-core-config")
|
@customElement("onboarding-core-config")
|
||||||
@ -31,15 +33,17 @@ class OnboardingCoreConfig extends LitElement {
|
|||||||
|
|
||||||
@state() private _working = false;
|
@state() private _working = false;
|
||||||
|
|
||||||
@state() private _name!: ConfigUpdateValues["location_name"];
|
@state() private _name?: ConfigUpdateValues["location_name"];
|
||||||
|
|
||||||
@state() private _location!: [number, number];
|
@state() private _location?: [number, number];
|
||||||
|
|
||||||
@state() private _elevation!: string;
|
@state() private _elevation?: string;
|
||||||
|
|
||||||
@state() private _unitSystem!: ConfigUpdateValues["unit_system"];
|
@state() private _unitSystem?: ConfigUpdateValues["unit_system"];
|
||||||
|
|
||||||
@state() private _timeZone!: string;
|
@state() private _currency?: ConfigUpdateValues["currency"];
|
||||||
|
|
||||||
|
@state() private _timeZone?: string;
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
@ -159,6 +163,35 @@ class OnboardingCoreConfig extends LitElement {
|
|||||||
</paper-radio-group>
|
</paper-radio-group>
|
||||||
</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=${this._working}
|
||||||
|
.value=${this._currencyValue}
|
||||||
|
@value-changed=${this._handleChange}
|
||||||
|
></paper-input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<mwc-button @click=${this._save} .disabled=${this._working}>
|
<mwc-button @click=${this._save} .disabled=${this._working}>
|
||||||
${this.onboardingLocalize(
|
${this.onboardingLocalize(
|
||||||
@ -180,10 +213,15 @@ class OnboardingCoreConfig extends LitElement {
|
|||||||
this._save(ev);
|
this._save(ev);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const input = this.shadowRoot!.querySelector(
|
const tzInput = this.shadowRoot!.querySelector(
|
||||||
"[name=timeZone]"
|
"[name=timeZone]"
|
||||||
) as PaperInputElement;
|
) as PaperInputElement;
|
||||||
input.inputElement.appendChild(createTimezoneListEl());
|
tzInput.inputElement.appendChild(createTimezoneListEl());
|
||||||
|
|
||||||
|
const cInput = this.shadowRoot!.querySelector(
|
||||||
|
"[name=currency]"
|
||||||
|
) as PaperInputElement;
|
||||||
|
cInput.inputElement.appendChild(createCurrencyListEl());
|
||||||
}
|
}
|
||||||
|
|
||||||
private get _nameValue() {
|
private get _nameValue() {
|
||||||
@ -210,6 +248,10 @@ class OnboardingCoreConfig extends LitElement {
|
|||||||
return this._unitSystem !== undefined ? this._unitSystem : "metric";
|
return this._unitSystem !== undefined ? this._unitSystem : "metric";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private get _currencyValue() {
|
||||||
|
return this._currency !== undefined ? this._currency : "";
|
||||||
|
}
|
||||||
|
|
||||||
private _markerLocation = memoizeOne(
|
private _markerLocation = memoizeOne(
|
||||||
(location: [number, number]): MarkerLocation[] => [
|
(location: [number, number]): MarkerLocation[] => [
|
||||||
{
|
{
|
||||||
@ -223,7 +265,16 @@ class OnboardingCoreConfig extends LitElement {
|
|||||||
|
|
||||||
private _handleChange(ev: PolymerChangedEvent<string>) {
|
private _handleChange(ev: PolymerChangedEvent<string>) {
|
||||||
const target = ev.currentTarget as PaperInputElement;
|
const target = ev.currentTarget as PaperInputElement;
|
||||||
this[`_${target.name}`] = target.value;
|
|
||||||
|
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) {
|
private _locationChanged(ev) {
|
||||||
@ -240,6 +291,7 @@ class OnboardingCoreConfig extends LitElement {
|
|||||||
this._working = true;
|
this._working = true;
|
||||||
try {
|
try {
|
||||||
const values = await detectCoreConfig(this.hass);
|
const values = await detectCoreConfig(this.hass);
|
||||||
|
|
||||||
if (values.latitude && values.longitude) {
|
if (values.latitude && values.longitude) {
|
||||||
this._location = [Number(values.latitude), Number(values.longitude)];
|
this._location = [Number(values.latitude), Number(values.longitude)];
|
||||||
}
|
}
|
||||||
@ -252,6 +304,9 @@ class OnboardingCoreConfig extends LitElement {
|
|||||||
if (values.time_zone) {
|
if (values.time_zone) {
|
||||||
this._timeZone = values.time_zone;
|
this._timeZone = values.time_zone;
|
||||||
}
|
}
|
||||||
|
if (values.currency) {
|
||||||
|
this._currency = values.currency;
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
alert(`Failed to detect location information: ${err.message}`);
|
alert(`Failed to detect location information: ${err.message}`);
|
||||||
} finally {
|
} finally {
|
||||||
@ -271,6 +326,7 @@ class OnboardingCoreConfig extends LitElement {
|
|||||||
elevation: Number(this._elevationValue),
|
elevation: Number(this._elevationValue),
|
||||||
unit_system: this._unitSystemValue,
|
unit_system: this._unitSystemValue,
|
||||||
time_zone: this._timeZoneValue || "UTC",
|
time_zone: this._timeZoneValue || "UTC",
|
||||||
|
currency: this._currencyValue || "EUR",
|
||||||
});
|
});
|
||||||
const result = await onboardCoreConfigStep(this.hass);
|
const result = await onboardCoreConfigStep(this.hass);
|
||||||
fireEvent(this, "onboarding-step", {
|
fireEvent(this, "onboarding-step", {
|
||||||
@ -311,6 +367,9 @@ class OnboardingCoreConfig extends LitElement {
|
|||||||
margin-top: 16px;
|
margin-top: 16px;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
a {
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,11 @@ export class DialogEnergyDeviceSettings
|
|||||||
@closed=${this.closeDialog}
|
@closed=${this.closeDialog}
|
||||||
>
|
>
|
||||||
${this._error ? html`<p class="error">${this._error}</p>` : ""}
|
${this._error ? html`<p class="error">${this._error}</p>` : ""}
|
||||||
|
<div>
|
||||||
|
${this.hass.localize(
|
||||||
|
`ui.panel.config.energy.device_consumption.dialog.selected_stat_intro`
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
<ha-statistic-picker
|
<ha-statistic-picker
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
|
@ -13,7 +13,6 @@ import {
|
|||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import "../../components/ha-menu-button";
|
import "../../components/ha-menu-button";
|
||||||
import "../../layouts/ha-app-layout";
|
import "../../layouts/ha-app-layout";
|
||||||
import { mdiCog } from "@mdi/js";
|
|
||||||
|
|
||||||
import { haStyle } from "../../resources/styles";
|
import { haStyle } from "../../resources/styles";
|
||||||
import "../lovelace/views/hui-view";
|
import "../lovelace/views/hui-view";
|
||||||
@ -60,13 +59,11 @@ class PanelEnergy extends LitElement {
|
|||||||
<ha-app-layout>
|
<ha-app-layout>
|
||||||
<app-header fixed slot="header">
|
<app-header fixed slot="header">
|
||||||
<app-toolbar>
|
<app-toolbar>
|
||||||
<div class="nav-title">
|
<ha-menu-button
|
||||||
<ha-menu-button
|
.hass=${this.hass}
|
||||||
.hass=${this.hass}
|
.narrow=${this.narrow}
|
||||||
.narrow=${this.narrow}
|
></ha-menu-button>
|
||||||
></ha-menu-button>
|
<div main-title>${this.hass.localize("panel.energy")}</div>
|
||||||
<div main-title>${this.hass.localize("panel.energy")}</div>
|
|
||||||
</div>
|
|
||||||
${this.narrow
|
${this.narrow
|
||||||
? ""
|
? ""
|
||||||
: html`
|
: html`
|
||||||
@ -75,11 +72,6 @@ class PanelEnergy extends LitElement {
|
|||||||
collectionKey="energy_dashboard"
|
collectionKey="energy_dashboard"
|
||||||
></hui-energy-period-selector>
|
></hui-energy-period-selector>
|
||||||
`}
|
`}
|
||||||
<a href="/config/energy?historyBack=1">
|
|
||||||
<mwc-icon-button>
|
|
||||||
<ha-svg-icon .path=${mdiCog}></ha-svg-icon>
|
|
||||||
</mwc-icon-button>
|
|
||||||
</a>
|
|
||||||
</app-toolbar>
|
</app-toolbar>
|
||||||
</app-header>
|
</app-header>
|
||||||
<hui-view
|
<hui-view
|
||||||
@ -128,12 +120,9 @@ class PanelEnergy extends LitElement {
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
.nav-title {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
hui-energy-period-selector {
|
hui-energy-period-selector {
|
||||||
width: 300px;
|
width: 100%;
|
||||||
|
padding-left: 16px;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { mdiChevronLeft, mdiChevronRight } from "@mdi/js";
|
import { mdiChevronLeft, mdiChevronRight } from "@mdi/js";
|
||||||
import { endOfToday, addDays, endOfDay, isToday, isYesterday } from "date-fns";
|
import { endOfToday, addDays, endOfDay, isToday, startOfToday } from "date-fns";
|
||||||
import { UnsubscribeFunc } from "home-assistant-js-websocket";
|
import { UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||||
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, state } from "lit/decorators";
|
||||||
@ -9,6 +9,7 @@ import { SubscribeMixin } from "../../../mixins/subscribe-mixin";
|
|||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import "@material/mwc-icon-button/mwc-icon-button";
|
import "@material/mwc-icon-button/mwc-icon-button";
|
||||||
import "../../../components/ha-svg-icon";
|
import "../../../components/ha-svg-icon";
|
||||||
|
import "@material/mwc-button/mwc-button";
|
||||||
|
|
||||||
@customElement("hui-energy-period-selector")
|
@customElement("hui-energy-period-selector")
|
||||||
export class HuiEnergyPeriodSelector extends SubscribeMixin(LitElement) {
|
export class HuiEnergyPeriodSelector extends SubscribeMixin(LitElement) {
|
||||||
@ -33,29 +34,34 @@ export class HuiEnergyPeriodSelector extends SubscribeMixin(LitElement) {
|
|||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isStartToday = isToday(this._startDate);
|
|
||||||
let label;
|
|
||||||
if (isStartToday) {
|
|
||||||
label = "Today";
|
|
||||||
} else if (isYesterday(this._startDate)) {
|
|
||||||
label = "Yesterday";
|
|
||||||
} else {
|
|
||||||
label = formatDate(this._startDate, this.hass.locale);
|
|
||||||
}
|
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
<div class="label">
|
||||||
|
${formatDate(this._startDate, this.hass.locale)}
|
||||||
|
</div>
|
||||||
|
|
||||||
<mwc-icon-button label="Previous Day" @click=${this._pickPreviousDay}>
|
<mwc-icon-button label="Previous Day" @click=${this._pickPreviousDay}>
|
||||||
<ha-svg-icon .path=${mdiChevronLeft}></ha-svg-icon>
|
<ha-svg-icon .path=${mdiChevronLeft}></ha-svg-icon>
|
||||||
</mwc-icon-button>
|
</mwc-icon-button>
|
||||||
<div class="label">${label}</div>
|
|
||||||
<mwc-icon-button label="Next Day" @click=${this._pickNextDay}>
|
<mwc-icon-button label="Next Day" @click=${this._pickNextDay}>
|
||||||
<ha-svg-icon .path=${mdiChevronRight}></ha-svg-icon>
|
<ha-svg-icon .path=${mdiChevronRight}></ha-svg-icon>
|
||||||
</mwc-icon-button>
|
</mwc-icon-button>
|
||||||
|
|
||||||
|
<mwc-button
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
.disabled=${isToday(this._startDate)}
|
||||||
|
@click=${this._pickToday}
|
||||||
|
>Today</mwc-button
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _pickToday() {
|
||||||
|
this._setDate(startOfToday());
|
||||||
|
}
|
||||||
|
|
||||||
private _pickPreviousDay() {
|
private _pickPreviousDay() {
|
||||||
this._setDate(addDays(this._startDate!, -1));
|
this._setDate(addDays(this._startDate!, -1));
|
||||||
}
|
}
|
||||||
@ -83,12 +89,30 @@ export class HuiEnergyPeriodSelector extends SubscribeMixin(LitElement) {
|
|||||||
.row {
|
.row {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
.label {
|
.label {
|
||||||
flex: 1;
|
padding: 0 8px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
|
mwc-icon-button {
|
||||||
|
--mdc-icon-button-size: 28px;
|
||||||
|
}
|
||||||
|
mwc-button {
|
||||||
|
padding-left: 8px;
|
||||||
|
--mdc-theme-primary: currentColor;
|
||||||
|
--mdc-button-outline-color: currentColor;
|
||||||
|
|
||||||
|
--mdc-button-disabled-outline-color: rgba(
|
||||||
|
var(--rgb-text-primary-color),
|
||||||
|
0.5
|
||||||
|
);
|
||||||
|
--mdc-button-disabled-ink-color: rgba(
|
||||||
|
var(--rgb-text-primary-color),
|
||||||
|
0.5
|
||||||
|
);
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,9 +60,9 @@ export class HuiViewEditor extends LitElement {
|
|||||||
|
|
||||||
get _type(): string {
|
get _type(): string {
|
||||||
if (!this._config) {
|
if (!this._config) {
|
||||||
return "masonary";
|
return "masonry";
|
||||||
}
|
}
|
||||||
return this._config.panel ? "panel" : this._config.type || "masonary";
|
return this._config.panel ? "panel" : this._config.type || "masonry";
|
||||||
}
|
}
|
||||||
|
|
||||||
set config(config: LovelaceViewConfig) {
|
set config(config: LovelaceViewConfig) {
|
||||||
@ -125,7 +125,7 @@ export class HuiViewEditor extends LitElement {
|
|||||||
attr-for-selected="type"
|
attr-for-selected="type"
|
||||||
@iron-select=${this._typeChanged}
|
@iron-select=${this._typeChanged}
|
||||||
>
|
>
|
||||||
${["masonary", "sidebar", "panel"].map(
|
${["masonry", "sidebar", "panel"].map(
|
||||||
(type) => html`<paper-item .type=${type}>
|
(type) => html`<paper-item .type=${type}>
|
||||||
${this.hass.localize(
|
${this.hass.localize(
|
||||||
`ui.panel.lovelace.editor.edit_view.types.${type}`
|
`ui.panel.lovelace.editor.edit_view.types.${type}`
|
||||||
@ -167,7 +167,7 @@ export class HuiViewEditor extends LitElement {
|
|||||||
...this._config,
|
...this._config,
|
||||||
};
|
};
|
||||||
delete newConfig.panel;
|
delete newConfig.panel;
|
||||||
if (selected === "masonary") {
|
if (selected === "masonry") {
|
||||||
delete newConfig.type;
|
delete newConfig.type;
|
||||||
} else {
|
} else {
|
||||||
newConfig.type = selected;
|
newConfig.type = selected;
|
||||||
|
@ -1052,7 +1052,10 @@
|
|||||||
"sub": "Tracking the energy usage of individual devices allows Home Assistant to break down your energy usage by device.",
|
"sub": "Tracking the energy usage of individual devices allows Home Assistant to break down your energy usage by device.",
|
||||||
"learn_more": "More information on how to get started.",
|
"learn_more": "More information on how to get started.",
|
||||||
"add_stat": "Pick entity to track energy of",
|
"add_stat": "Pick entity to track energy of",
|
||||||
"selected_stat": "Tracking energy for"
|
"selected_stat": "Tracking energy for",
|
||||||
|
"dialog": {
|
||||||
|
"selected_stat_intro": "Select the entity that represents the device energy usage."
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"helpers": {
|
"helpers": {
|
||||||
@ -2943,7 +2946,7 @@
|
|||||||
},
|
},
|
||||||
"type": "View type",
|
"type": "View type",
|
||||||
"types": {
|
"types": {
|
||||||
"masonary": "Masonary (default)",
|
"masonry": "Masonry (default)",
|
||||||
"sidebar": "Sidebar",
|
"sidebar": "Sidebar",
|
||||||
"panel": "Panel (1 card)"
|
"panel": "Panel (1 card)"
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user